JavaScript 闭包

闭包是JavaScript中非常重要的特性,看过很多讲闭包的,最近在Stoyan Stefanov著的一本 Object-Oriented JavaScript中看到的讲解觉得十分易于理解,在此分享下:

现在,让我们先通过图示的方式来介绍一下闭包。
首先是全局作用域,我们可以将其看做包含一切的宇宙。
这里写图片描述

其中,可以包含各种变量(如a)和函数(如F)。
这里写图片描述
每个函数也都会拥有一块属于自己的私用空间,用以存储一些别的变量(和函数),所以,我们最终可以把示意图画成这样:
这里写图片描述
在上图中,如果我们在a点,那么就位于全局变量中,而如果是在b点,我们就在函数F的空间里,在这里我们既可以访问全局空间,也可以访问F空间,如果我们在c点,那就位于函数N中,这里我们可以访问的空间包括全局空间、F空间和N空间。其中,a和b之间是不连通的,因为b在F以外是不可见的,但如果愿意的话,我们是可以将c点和b点连通起来的,或者说将N与b连通起来,当我们将N的空间扩展到F以外,并止步于全局空间以内时,就产生了一件有趣的东西——闭包。
这里写图片描述
知道接下来发生神马不?N将会和a一样置身于全局空间,而且由于函数还记得在被定义时所设定的环境,因此它依然可以访问F空间并使用b。这很有趣,因为现在N和a处于同一个空间,但N可以访问b,而a不能。
那么,N究竟是如何突破作用域链的呢?我们只需要将它们升级为全局变量(不使用var语句)或通过F传递(或返回)给全局空间即可。下面,我们来看看具体是怎么做的。

闭包①
下面,我们先来看一个函数:

function f(){
    var b = “b”;
    return function(){
        return b;
    }
}

这个函数含有一个局部变量b,它在全局空间里是不可见的。

b //这是指输入命令b
b is not defined //这是执行结果

接下来,我们来看一下f()的返回值,这是另一个函数,我们可以把它看作上图中的函数N,该函数有自己的私用空间,同时也可以访问f()空间和全局空间,所以b对它来说是可见的,因为f()是可以在全局空间中被调用的(它是一个全局函数),所以我们将它的返回值赋值给另一个全局变量,从而生成一个可以访问f()私有空间的新全局函数。

var n = f();
n();
“b”

闭包②
下面这个例子最终结果与之前相同,但在实现方法上有一些细微的不同,在这里f()不再返回函数了,而是直接在函数体内创建一个新的全局函数。
首先,我们需要声明一个全局函数的占位符,尽管这种占位符不是必须的,但最好还是声明一下,然后,我们就可以将函数f()定义如下:

var n;
function f(){
    var b = “b”;
    n = function (){
        return b;
    }
}

现在,让我们来看看f()被调用时会发生神马:

f();
我们在f()中定义了一个新的函数,并且没有在这里使用var语句,因此它应该是属于全局的,由于n()是在f()内部定义的,它可以访问f()的作用域,所以即使该函数后来升级成了全局函数,但它仍然可以保留对f()作用域的访问权。
n();
“b”

闭包③
根据目前的讨论,我们可以说,如果一个函数需要在其父级函数返回之后留住对父级作用域链的话,就必须要为此建立一个闭包。
而由于函数通常都会将自身的参数视为局部变量。因此我们创建返回函数时,也可以令其返回父级函数的参数。例如:

function f(arg) {
var n = function () {
    return arg;
}
arg++;
return n;
}

然后我们可以这样调用函数:

var m = f(123);
m();
124

请注意,当我们的函数函数被调用时,arg++已经执行过一次递增操作了,所以m()返回的是更新后的值,由此我们可以看出,函数所绑定的作用域本身,而不是该作用域中的变量或变量当前所返回的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值