美文网首页
作用域链和闭包总结

作用域链和闭包总结

作者: Lwq_长路漫漫 | 来源:发表于2017-05-08 21:15 被阅读0次

    JavaScript作用域

    简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

    <script type="text/javascript">
        var v = 20; //定义了一个全局变量,那么这个变量在当前的JS脚本部分都可以
         function(){
         var v = 10;//在函数里面定义了一个局部变量,在函数外部无法访问到这个局部变量
    }
        alert(v); //弹出:20
                  访问到。
    </script>
    <script type="text/javascript">
        //因为v是全局变量,所以这里仍然可以访问到。
        alert(v);  //弹出:20
    </script>
    

    在函数内部所有末定义直接赋值的变量自动声明为拥有全局作用域,例如:

    function sum(){
        var v = 20;
        b = 10;
        alert(v);
    }
    sum(); //20
    alert(b); //10
    alert(v); //脚本错误
    

    JavaScript中有没有块级作用域?

    <script type="text/javascript">
      var m = 5;
      if(m == 5){
        var n = 10;
      }
      alert(n); //输出10- JavaScript的作用域是按照函数来划分的JavaScript没有块级作用域
    
    </script>
    

    当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。

    function add(num1,num2) {
        var sum = num1 + num2;
        return sum;
    }
    

    在函数add创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,

    我们可以看到,由于函数作用域的特性,局部变量在整个函数体始终是由定义的,我们可以将变量声明”提前“到函数体顶部,同时变量初始化还在原来位置。

    var scope="global";  
    function t(){  
        console.log(scope);  // 是"undefined",而不是 "global"
        var scope="local"  
        console.log(scope);  //是"local"
    }  
    t();
    

    当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显name是"slwy",但执行ss()时,name是 tlwy。

    name="lwy";  
    function t(){  
        var name="tlwy";  
        function s(){  
            var name="slwy";  
            console.log(name);  
        }  
        function ss(){  
            console.log(name);  
        }  
        s();  
        ss();  
    }  
    t();
    
    闭包

    闭包是指有权访问另一个函数作用域中的变量的函数

    <script type="text/javascript">
        function createSumFunction(num1, num2){
            return function () {
                return num1 + num2;
            };
        }
    
        var sumFun = createSumFunction(3, 4);
        var sum = sumFun();
        alert(sum);
    </script>
    

    闭包中使用的局部变量的值,一定是局部变量的最后的值。

    function a(){
      var n = 0;
      function inc() {
        n++;
        console.log(n);
      }
      inc(); 
      inc(); 
    }
    a(); //控制台输出1,再输出2
    

    常见的陷阱,以为输出 0~9 ,万万没想到输出10个10

    function createFunctions(){
      var result = new Array();
      for (var i=0; i < 10; i++){
        result[i] = function(){
          return i;
        };
      }
      return result;
    }
    var funcs = createFunctions();
    for (var i=0; i < funcs.length; i++){
      console.log(funcs[i]());
    }
    

    上面的解释就是:

    var result = new Array(), i;
    result[0] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
    result[1] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
    ...
    result[9] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
    i = 10;
    funcs = result;
    result = null;
     
    console.log(i); // funcs[0]()就是执行 return i 语句,就是返回10
    console.log(i); // funcs[1]()就是执行 return i 语句,就是返回10
    ...
    console.log(i); // funcs[9]()就是执行 return i 语句,就是返回10
    

    闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!另外使用闭包也要注意变量的值是否符合你的要求,因为他就像一个静态私有变量一样。

    相关文章

      网友评论

          本文标题:作用域链和闭包总结

          本文链接:https://www.haomeiwen.com/subject/fwxkattx.html