作用域和闭包

每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但是有些不可以,这些属性仅供JavaScript引擎存取,[[scope]]就是其中一个。

[[scope]]指的就是我们所说的作用域链,其中存储了运行期上下文的集合

一个函数被定义的时候,他的作用域链中存放着全局的变量对象,当函数开始被执行的时候,就会创建一个执行期上下文,放在作用域链的第一位,也就是先在自己的执行期上下文中寻找变量,之后沿着作用域链一级一级向上查找。

运行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象,一个执行期上下文定义了一个函数 执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕后,它所产生的执行上下文被销毁

只有表达式才能被执行

立即执行函数写法:

1:(function(){}())  W3C建议使用这种写法

2:(function(){})()

3:var test = function(){}()

定义:此类函数没有声明,在一次执行后就立即释放,适合做初始化工作。直接就是表达式

执行位置不在定义位置

function test(){
    var arr = [];
    for(var i = 0;i<10;i++){//这个for循环的作用是给arr数组中添加十个函数
        arr[i] = function(){//这个是个表达式,系统不关心函数中写的什么,函数目前只是一个定义阶段,并不是执行阶段,所以里面的i并不会发生变化
            document.write(i+" ");
          }
    }
    return arr;
}
var myArr = test();
for(var j = 0;j<10;j++){//在这里开始执行里面的函数,所以在这里开始索取i,此时i已经是10了
    myArr[j]();
}

这个是个10对1的闭包,每一个都可以访问test中的ao,此时ao中的i已经是10 了,经过了十次循环后

函数在被定义的时候是没有意义的,只有在被执行的时候,你才需要知道它的变量,此时,你需要找它的作用域链,一级一级往上找

上面这个例子最后输出十个10,若是想要输出0-9,则可以这样改

function test(){
    var arr = [];
    for(var i = 0;i<10;i++){
        (function(j){
                arr[j] = function(){
                document.write(j +' ');
            }
        }(i));//把中间的for循环中变成一个立即执行函数
    }
    return arr;
}
var myArr = test();
for(var j = 0;j<10;j++){
    myArr[j]();
}

闭包:当内部函数被保存到外部时,将会生成闭包,闭包会导致原有作用域链不释放,造成内存泄漏

为什么要使用闭包?

js中特殊的变量作用域,作用域有两种,局部作用域和全局作用域,内部函数可以访问外部函数的作用域链,外部函数不能访问内部函数的作用域链,所以使用闭包,内部函数可以获取到外部函数的变量,并且变量会被保存到内存中不会被销毁。

你可能感兴趣的:(前端)