JavaScript闭包-闭包中的变量和this对象
2016-10-21 16:51
281 查看
在JavaScript中作用域链的机制会引发一些副作用:闭包只能够获取包含函数中任何变量的最后一个值。在使用闭包的时候,我们一定要注意变量值的问题,因为这是经常会出错的地方。
下面我们以一个非常极端的例子来说明这个问题,在实际开发中我们一般不会这样编写代码。这个例子的代码如下:
执行上面的代码,我们预期会在页面中打印出0-9,但是实际上会打印10个10。我们来分析一下这段代码:实现代码中创建了一个函数fn1,在函数中创建了一个数组对象,并通过一个for循环为数组赋值,循环了10次,每一次往数组中填充一个匿名函数返回值,最后返回数组对象。接着获取fn1函数的引用,然后通过循环在页面中输出数组中的值。
上面的程序的作用域链内存模型如下图所示:
从图中我们可以看到,每次在fn1函数中的循环都会产生一个匿名函数,它们有各自的作用域链,它们的作用域链的高位都指向全局作用域,中间位指向外层的fn1作用域,低位才是指向自己的作用域。
当函数fn1执行完毕之后,fn1作用域中的属性
在匿名函数执行的时候,它在自己的空间中查找属性
解决这个问题的方法是在匿名函数中再返回一个匿名函数,并通过一个变量来保存当前的数值。代码如下:
此时,
上面的代码会产生20个匿名函数的作用域,如果代码中不是简单的返回值,而是一些更复杂的操作,将会占用大量的内存空间。
闭包中的this对象
在闭包中使用
上面的代码中,我们调用
解决这个问题的方法是在
下面我们以一个非常极端的例子来说明这个问题,在实际开发中我们一般不会这样编写代码。这个例子的代码如下:
上面的程序的作用域链内存模型如下图所示:
从图中我们可以看到,每次在fn1函数中的循环都会产生一个匿名函数,它们有各自的作用域链,它们的作用域链的高位都指向全局作用域,中间位指向外层的fn1作用域,低位才是指向自己的作用域。
当函数fn1执行完毕之后,fn1作用域中的属性
i的值为10,此时GC开始回收fn1,但是它发现有匿名函数指向fn1的作用域,所以fn1的作用域不会被回收。
在匿名函数执行的时候,它在自己的空间中查找属性
i,但是没有找到,于是就到它上级的fn1作用域中去查找,此时,fn1作用域中的i值为10,所以所以匿名函数都会获得相同的i值:10。
解决这个问题的方法是在匿名函数中再返回一个匿名函数,并通过一个变量来保存当前的数值。代码如下:
num的值保存在每一个匿名函数自己的作用域中,并且数值刚好等于每次循环的索引值。这样,在每次调用匿名函数的时候,它会在自己的空间中找到
num属性,并且这些
num的值都是不同的,同时也不会再到fn1函数作用域中去查找
i属性。
上面的代码会产生20个匿名函数的作用域,如果代码中不是简单的返回值,而是一些更复杂的操作,将会占用大量的内存空间。
闭包中的this对象
在闭包中使用
this对象也会出现一些意想不到的问题。
this对象是在运行时基于函数的执行环境绑定的:对于全局函数,
this对象就是
window,而当函数在作为某个对象的方法被调用时,
this就是那个对象。在匿名函数中,
this对象通常是指向
window的。我们来看下面的例子:
person对象的
say()方法时,打印出来的不是
person对象的名字,而是全局的名字“window”。当完成
person.say()之后,该函数调用完毕,在该函数调用结束之前,
this是在指向
person的,但是在调用匿名函数的时候,
this就指向
window了,所以得到的结果是“window”。
解决这个问题的方法是在
say()方法中将
this引用赋值给一个临时变量。代码如下:
相关文章推荐
- JavaScript核心:对象 原型链 构造函数 执行上下文栈 执行上下文 变量对象 活动对象 作用域链 闭包 This 总结
- JavaScript的小小总结!变量类型、对象声明、this用法、原型、匿名函数、闭包和自执行函数
- JavaScript之闭包的实现、闭包中的this对象
- JavaScript 变量作用域、this、闭包
- javascript 闭包 this 匿名函数 匿名对象
- javascript对象小探之六——全局变量、变量提升和this
- javascript 中使用变量存储的函数与不使用变量存储的函数的加载区别,以及其中this对象的区别
- JavaScript高级程序设计之函数表达式之闭包之关于 this 对象第7.2.2讲笔记
- JavaScript 变量作用域、this、闭包
- JavaScript关于闭包,匿名函数,this,对象等的一些理解
- 利用闭包使用JavaScript语言模拟对象的私有变量和方法
- JavaScript的变量及函数(变量提升、嵌套作用域、条件语句、严格模式、IIFE、闭包、模块化、this、原型)
- 深入理解JavaScript作用域、变量对象、闭包
- JavaScript执行环境 + 变量对象 + 作用域链 + 闭包
- javascript中的闭包循环变量只能取最后一个值问题
- JavaScript面向对象程序设计(7): 闭包
- Javascript 的词法作用域、调用对象和闭包
- JavaScript 的变量作用域及闭包
- [JAVASCRIPT] this 对象
- JavaScript 嵌套函数指向this对象错误的解决方法