作用域链和闭包总结

2017-05-08  本文已影响0人  Lwq_长路漫漫

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

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

上一篇 下一篇

猜你喜欢

热点阅读