今天我们学习了 Javascript 中作用域链和闭包的相关知识,在此写一篇文章来总结一下,加深自己对这两个知识点的理解。
作用域链:
要了解作用域链,必须先明白执行环境(execution context ),执行环境定义了变量或函数有权访问的其他数据。定义了他们的行为。每个执行环境都有一个和它关联的变量对象,在这个执行环境中的所有变量和函数都保存在这个对象中。在web浏览器中,全局执行环境的变量对象就是 window 对象,所有的全局变量和函数都是 window 的属性和方法。而对于函数来说,变量对象就是这个函数的 活动多象。
作用域链与一个执行环境相关,作用域链用于在标示符解析中变量查找。
函数也是对象,也拥有属性和方法,每个函数中都有一个内部属性 [[ Scope ]],这个属性指向函数的作用域链。作用域链中储存的是每个执行环境中相关的变量对象。当申明一个函数,那么就会创建出这个函数的作用域链,这个作用域链此时只包含一个变量对象,就是 window 对象。当调用这个函数的时候,会先创建一个执行环境,这个执行环境有自己的作用域链,作用域链里初始化为这个函数里所有的变量和对象,再创建这个执行环境相关的变量对象,变量对象会储存这个函数里所有的变量和对象。把变量对象储存在作用域的顶端,执行函数时,变量查找从作用域顶端开始查找,直到作用域的末端。就形成了作用域链。
请看下列代码:
内部函数的作用域图:
闭包:
在上面的代码中,createSumFunction函数返回了一个匿名函数,而这个匿名函数使用了createSumFunction函数中的局部变量(参数),即使createSumFunction这个函数执行结束了,由于作用域链的存在,他的局部变量在匿名函数中仍然可以使用,这个匿名函数就是闭包。
闭包用一句简单的话来描述:
闭包就是指有权访问另一个函数作用域中的变量的函数。
闭包是一种特殊的对象。它是由函数和创建此函数的环境组成。环境由创造闭包时作用域中所有的局部变量组成。上面代码中,sumFun就是一个闭包,由匿名函数和创建闭包是所申明的num1 和num2两个局部变量组成。
闭包的应用:
请看下面代码:
以上代码中,虽然函数申明在num++之前。但是函数调用的时候num 已经++ 过了,所以最后的num值为6.由此可知:闭包中使用局部变量的值,一定是这个变量的最新值(最后的值)。
请看一下代码:
此列是经典的for循环问题。当运行的时候会发现,无论你点击哪个按钮,都是弹出 “我是底4个按钮”,这就是闭包所导致的。因为所取 i 的值,总是最新的值。
解决方案:
好了,本次总结就到此结束了,因为刚刚学习,总结得不好,也不到位,希望各位能够理解支持,也能把自己的建议告诉我,我定积极进取。