闭包(closure)的简单介绍

定义:函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中成为“闭包”。

作用域链(scope chain) 的定义:
每一段JavaScript代码(全局代码或函数)都有一个与之关联的作用域链,这个作用域链是一个对象列表或者链表,这组对象定义了这段代码中的变量。当JavaScript需要查找变量x的值的时候(这个过程叫做变量解析(variable resolution)),它会从链的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中不存在名为x的属性,则会继续查找下一个对象,以此类推。

var countInteger = (function f() {                   //定义函数并立即调用
     var counter = 0;                                   //私有变量
     return function g(){return counter++;};        //函数f返回的是一个函数(返回的这个函数嵌套在f内)。私有变量保存在函数体作用域内。
}());
console.log(countInteger());    //0
console.log(countInteger());    //1
console.log(countInteger());    //2

我们分析上述的代码:
代码中定义了一个立即执行的函数var countInteger = (xxx); ,而这个立即执行的函数f返回了另外一个函数g,因此,我们最终给变量countInteger赋的值为这个嵌套函数g。这个嵌套函数g是可以访问作用域内的变量的,而且可以访问外部函数中定义的counter变量。当外部函数返回之后,其他任何代码都无法访问counter变量,只有内部的函数才能访问它。

值得注意的是,返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

下面我们来看一个例子,我们想使用闭包,将数字0-9利用闭包存储到数组中:

function constfuncs() {
    var funcs = [];
    for(var i = 0; i < 10; i++)
        funcs[i] = function() {return i; };
    return funcs;
}
var funcs = constfuncs();
console.log(funcs[1]());     //返回值是?-->10,并非1
console.log(funcs[5]());    //返回值是?-->10,并非5

上面的这段代码创建了10个闭包,并将它们存储到一个数组中。这些闭包都是在同一个函数调用中定义的,因此它们可以共享变量i。当constfuncs()返回时,变量i的值都是10,所有的闭包都共享这一个值。

我们只要修改一下上述的代码,就可以得到我们想要的结果:

function constfuncs() {
    var funcs = [];
    for(var i = 0; i < 10; i++)
        funcs[i] = (function(n) { return function(){
            return n;
    }}(i));
return funcs;
}
var funcs = constfuncs();
console.log(funcs[1]()); //返回值是?-->1
console.log(funcs[5]()); //返回值是?-->5
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容