闭包——到底是什么?

本文详细解释了闭包的概念,包括其构成要素及为何函数和词法环境的结合才是真正的闭包。并通过示例展示了闭包如何解决实际编程中的常见问题,如循环添加点击事件时的索引问题、模拟私有变量以及在面向对象编程中的作用。

闭包的概念

闭包是函数和声明该函数的词法环境的组合。

这是官方文档,给出的标准的闭包定义。它是什么意思呢?

它说明了两个方面,一方面着重强调了函数,一方面着重强调了词法环境。

有人说,函数套函数,就是闭包!我认为,这是不正确的。

函数套函数,说明了闭包的函数声明,但是忽略了函数的词法环境。

函数的词法环境

function test(){
    var a = 1;
    function test1(){ 
        console.log(a);
    }
    test1();
}

这个示例中,我们在test函数中定义了test1函数,对于test1函数而言,var a = 1,就是它的词法环境。我在我的函数内部,可以访问外部的变量。

那这个就是闭包吗?显然不是!因为test函数执行完毕,就释放了所有的空间。

闭包

那到底什么才算是闭包?

把上面的示例稍微改造一下:

function test(){
    var a = 1;
    return function(){
        console.log(a);
    }
}

我们在执行test函数的时候,返回了一个function。而这个返回的function可以访问函数内部的变量 a。

一般而言,一个函数在执行完毕,就释放了自身的内存空间,但是这个test函数执行了,你还不能释放它的内存空间,因为它的返回值是一个函数!!这个函数还在使用变量 a 呢!!释放了空间就会出问题!!

所以,这样就形成了一个闭包!执行了test函数,test函数内部的词法环境还没有被释放,同时它的返回值是一个function,可以访问test词法环境中的变量。

闭包有啥用呢

第一、解决循环添加点击事件的索引i 的问题。

for(var i = 0; i < list.length; i++){
    list[i].onclick = function(){
        console.log(i)
    }
}

打印出的东西绝对不是0,1,2,3。。。。

使用闭包就能完美解决这个问题。

第二、模拟私有变量。

在设计模式中,有一种模式,叫做模块模式。

var module = (function(){
    var a = 1;
    function init(){ 
        console.log(a);
    }
    return {
        init: init
    }
})();

其中,a就是module模块的私有变量,很多框架就是基于这样的模式来实现的。比如zepTo.js、underscore.js等等。

第三、闭包在面向对象中的思考

我们在创建对象的时候,由于闭包会影响函数的性能。所以函数一般定义在原型上。

最终形成了面向对象中的实例属性、原型方法的构造方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值