时间:2022-06-28 09:18:19 | 栏目:JavaScript代码 | 点击:次
什么是闭包: 闭包是一个存在内部函数的引用关系。 该引用指向的是外部函数的局部变量对象(前提是内部函数使用了外部函数的局部变量) 闭包的作用: 延长外部函数变量对象的生命周期 使用闭包能够间接的从函数外部访问函数内部的私有变量
function outer() { var a = 1 function inner() { console.log(a) //1 } inner() } outer()
function createFunc() { var result = new Array() for (var i = 0; i < 10; i++) { result[i] = function () { console.log(i) } } return result } var result = createFunc() result[0]() //10 result[1]() //10 result[2]() //10 result[3]() //10 result[4]() //10 result[5]() //10 result[6]() //10 result[7]() //10
首先在代码执行前,会先创建一个全局的对象,其中包含着全局的属性,并且将其放入全局上下文作用域链顶端,并且也将其放入每一个函数的作用域链顶端。以这个例子为例。如图所示
在初始化结束后,开始执行代码,此时就会创建一个新的对象,叫做Active Object,其中放入一些参数,并且将其压入createFunc函数的作用域链中。
因为在createFunc中仍然定义函数result[i]..,所以在执行代码前,该函数会形成作用域链。
此时开始执行createFunc函数,当指向完毕后,createFunc中的作用域链表现为。如下图所示。此时result为一个数组。并且Active object已经从createFunc作用域链的顶部删除。
此时开始执行result[0](这里以result[0]为例,其他的一样),此时执行result[0]之前,应该创建一个新的Active object
对象,将其放入result[0]
执行作用域栈中。如图所示
此时函数执行中需要访问i,但是在active object并不存在i,所以此时需要沿着作用域链进行查找,在createFunc中找到i,并且i的值为10,所以最终打印的值都是10。在createFunc执行完毕后,其创建的对象并没有被垃圾回收掉,因为在result[0]中的i依然保持对该对象的引用。
这个例子的解决方法如下所示,就是设置一个立即执行函数,每一个下标对应的函数,都是立即执行函数,当立即执行函数执行时,每一个函数的上下文对象中都会存在为正确的下标值。
function createFunc() { var result = new Array() for (var i = 0; i < 10; i++) { result[i] = (function (num) { return function() { console.log(num) } })(i) } return result } var result = createFunc() result[0]() //0 result[1]() //1 result[2]() //2 result[3]() //3 result[4]() //4 result[5]() //5 result[6]() //6 result[7]() //7