javascript执行上下文、作用域与闭包(第七篇)---关于闭包典型例子的理解

在上一篇里,我留下了一个例子,如果理解了这个例子,我觉得闭包对你已经不是问题了。

这个例子如下:

function A(){
    var count=0;
    function B(){
        count++;
        alert(count);
    }
    return B;

}
 var c=A();
 c();//1
 c();//2
 c();//3

咱们一步一步地来解释这个结果。(演示时我省掉了作用域的注释,直接用框框表示了)

第一步,代码执行前生成全局上下文环境,并在执行时对其中的变量进行赋值。此时全局上下文环境是活动状态:
javascript执行上下文、作用域与闭包(第七篇)---关于闭包典型例子的理解_第1张图片

第二步,执行第20行代码时,调用A(),产生A()执行上下文环境,压栈,并设置为活动状态
javascript执行上下文、作用域与闭包(第七篇)---关于闭包典型例子的理解_第2张图片

第三步,当A()调用完成,回到全局上下文。按理说应该销毁掉A()的执行上下文环境,但是因为执行A()时,返回的是一个函数。函数的特别之处在于可以创建一个独立的作用域,因为“return”把A()上下文和B()上下文联系到了一起,所以为了B()上下文,暂时不能把A()上下文销毁。
javascript执行上下文、作用域与闭包(第七篇)---关于闭包典型例子的理解_第3张图片

第四步,执行完第20行时,全局上下文里变量c已经不是undefined,而是c:function (赋值语句是先调用A(),再给变量c赋值),全局上下文环境将变为活动状态,但是A()上下文环境依然会在执行上下文栈中,
javascript执行上下文、作用域与闭包(第七篇)---关于闭包典型例子的理解_第4张图片

第五步,执行到第21行,执行c(),即执行B(),创建B()上下文环境,并将其设置为活动状态, B()执行上下文(简称:上下文)创建阶段无新的变量声明,只有在执行阶段有对count变量的赋值语句,但在B()的上下文里没有count变量,所以要往创建B()的作用域所对应的上下文里找,确实在A()的上下文里找到了count变量,所以count此时的值为1.
javascript执行上下文、作用域与闭包(第七篇)---关于闭包典型例子的理解_第5张图片

第六步:当第20行的c()调用完后,变把其创建的上下文弹出上下文栈即销毁,执行第21行c()的过程和执行第20行的c()相同,所以不难理解第二次执行c(),结果是2,第三次执行,结果是3

第七步,执行完所有语句,便把所有的上下文销毁。

如果对这个过程仍就有疑问的,赶紧把我一系列的文章看一看,一定要耐着性子从头看到尾,应该会有帮助的哦。

到这里,闭包系列的文章就结束了。在写这些文章的同时,我也体会到,如果真的把背后的原理弄清楚了,编程就不会是一件难事。

写在后面

至此,本系列的文章已经完结了,但如果你最先阅读本系列的文章,如果你觉得自己已经对闭包有足够了解了,那么事实上可能并未,这系列文章对某些关键的知识点的解释仍有不正确之处,但这并不妨碍你对闭包的第一印象,编程是一门严谨的技术,所以如果热爱,可以耐心阅读我的第二个系列的文章,第二系列从底层代码解释了闭包是如何造成的。

第二系列文章的地址收录在我的这篇文章里 厚积薄发—从此再也不用担心闭包问题


本系列文章地址:
javascript执行上下文、作用域与闭包(第一篇)—执行上下文
javascript执行上下文、作用域与闭包(第二篇)—作用域
javascript执行上下文、作用域与闭包(第三篇)—自由变量与作用域链
javascript执行上下文、作用域与闭包(第四篇)—作用域与执行上下文
javascript执行上下文、作用域与闭包(第五篇)—一个例子的理解
javascript执行上下文、作用域与闭包(第六篇)—闭包
javascript执行上下文、作用域与闭包(第七篇)—关于闭包典型例子的理解

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