• 理解javascript的闭包,原型,和匿名函数及IIFE


    理解javascript的闭包,原型,和匿名函数(自己总结)

    一 .>关于闭包

    理解闭包 需要的知识
    1.变量的作用域

    例1:
    var n =99; //建立函数外的全局变量
    function readA(){
        alert(n); //读取全局变量
    }
    readA(); //执行此函数
    例2:
    function readB(){
        var c = 9;
        function readC(){
            console.log(c); //ok c可见
        }
        return readC;
    }
    alert(c); //error  c is not defined.

        note:  函数内部声明变量c时,一定要加上 var,否则 c会成为一个全局变量


    所以函数内可见全局变量,函数内的局部变量却对外不可见
    js的作用域是链式的,父对象里的变量总对子对象可见,子对象的对象却对父对象不可见
    当我们要获取函数内的内部变量

    于是有了例3:

    function readB(){
       var c = 9;
       function readC(){
           console.log(c);
       }
       return readC();
    }
    readB();

    闭包很类似基于此做了一个变式

    function readB(){
        var c = 9;
        function readC(){
           console.log(c);
        }
        return readC;
    }
    var res = readB();
    res();

    note:
    1.慎用闭包,注意内存占用,因为它会保存父函数的状态
    2.不要随便改变父函数内部变量的值

    理解闭包
       note: this 指包含它的函数被执行时所属的对象

    例1:
    var name = "The Window";
    
    var object = {
        name : "My Object",
    
      getNameFunc : function(){   //此时this (这个执行函数)是属于object对象的,是object对象下的一个属性的值
          return function(){      //此时this (这个执行函数)是一个匿名函数,从根对象window生成,是属于window
            return this.name;
        };
      }
    };
    console.log(object.getNameFunc()());  //the window 
    例2:
    var name = "The Window";
    
    var object = {
        name : "My Object",
    
        getNameFunc : function(){
            var that = this;
          return function(){
              return that.name;
          };
    
        }
    };
    console.log(object.getNameFunc()());   //My Object

    二 .>匿名函数 IIFE
    直接定义一个匿名函数 然后调用这个匿名函数,这种形式在jquery插件的定义时很常见

    1.通过函数字母量的方式. 先声明一个匿名函数,然后执行它

    ( function(){
        console.log('excute self');
    }) ();

    2.通过优先表达式的方式 , 由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数

    (
        function () {
            alert(2);
        }
        ()
    );


    3.void操作符 用void操作符去执行一个没有用圆括号包围的一个单独操作数

    void function(){ console.log('void') } ();
    在Bootstrap源码(具体请看《Bootstrap源码解析》)和其他jQuery插件经常看到如下的写法: 
    Js代码  
    
        +function ($) {   
          
        }(window.jQuery);  
    
     这种写法称为:
    IIFE (Imdiately Invoked Function Expression 立即执行的函数表达式)
    
    一步步来分析这种代码:
    先弄清 函数表达式(function expression)和 函数声明(function declaration)的区别:
    
    函数表达式  Function Expression - var test = function() {}; 
    函数申明     Function Declaration - function test() {};
    
    函数表达式中的函数可以为匿名函数,也可以有函数名,但是该函数实际上不能直接使用,只能通过表达式左边的变量 a 来调用
    var a = function(){  
      alert('Function expression');  
    }  
    var b = new a(); 
    
    函数声明时必须有函数名
    function a(){  
      alert('Function declaration');  
    }  
    a(); 
    
    这是一个匿名函数
    function () {  
      
    }  
    你也许注意到匿名函数在console下会报错。console的执行和报错如下:
     function(){} 
    SyntaxError: Unexpected token (
    
    通过一元操作符+变成了函数表达式。
    也可以使用 - ~ !等其他一元运算符或者括号,目的是为了引导解析器,指明运算符附近是一个表达式。以下是三种经典方式 :
    +function () {   
      
    };  
      
    (function () {  
      
    });  
      
    void function() {  
      
    };  
    
    函数表达式通过 末尾的() 来调用并运行。就是一个IIFE
    +function () {   
      
    }();  
      
    (funtion () {  
      
    })();  

    参考:http://suqing.iteye.com/blog/1981591/

    三 .>关于prototype

    原型 prototype

    理解js中的protitype首先需要明白js的面向对象设计
     

    function People(name){
        this.name = name;
    
        console.log(this);  //Window 或者 object { name: 'xxx' }
        this.introduce = function(){    //实例对象方法
            console.log(this.name);
        }
    }
    
    new People('leon').introduce();
    
    //这里有一个非常有趣的现象,结合前面的来看的话,
    //首先function people里的this指向的默认是Window对象
    //当 调用 People();时 this 输出为 Window对象
    //但一旦调用new People('xx')时, this 输出为 {name:'xx'}
    //其实也很好理解,一旦new ,便新建了一个对象

    实例对象方法只能这样 new People('leon').introduce(); 调用 因为它使用前必须初始化

    类的对象的静态方法

    var People = {};  //等于一个对象 {} 或者 function 数组都可以 此时People需要是引用类型
    People.sayhi = function(to_who){
        console.log('hi '+ to_who);
    }
    
    People.sayhi('lee'); //调用时这样调用


    原型方法

    var People = function(){};             // People 必须为一个 function(){} 即为一个类,不能是对象或值类型或其他引用类型
    People.prototype.meet = function(meet_who) {
        console.log('I am '+this.name + ',going to meet ' + meet_who);
    };

    new People('lee').meet('xx');

    原型方法只能由该类的对象 调用
     A.prototype = new B(); 
    原型看起来很像继承,但其实不是,它更像clone更准确
    如果出现了父类和子类出现了重名的属性,采取就近原则,如果找不到一级一级向上找,如果要指定调用上级的属性,使用call方法

    function baseClass()
    {
      this.showMsg = function()
      {
         alert("baseClass::showMsg");   
      }
    }
    
    function extendClass()
    {
    }
    
    extendClass.prototype = new baseClass();
    var instance = new extendClass();
    instance.showMsg(); // 显示baseClass::showMsg

    extendClass.prototype = new baseClass();
    var instance = new extendClass();

    var baseinstance = new baseClass();
    baseinstance.showMsg.call(instance);

    obj1.func.call(obj);

  • 相关阅读:
    BZOJ5212 ZJOI2018历史(LCT)
    BZOJ5127 数据校验
    253. Meeting Rooms II
    311. Sparse Matrix Multiplication
    254. Factor Combinations
    250. Count Univalue Subtrees
    259. 3Sum Smaller
    156. Binary Tree Upside Down
    360. Sort Transformed Array
    348. Design Tic-Tac-Toe
  • 原文地址:https://www.cnblogs.com/isdom/p/webclips012.html
Copyright © 2020-2023  润新知