2020-04-29: 第七章:关于this对象

7.2.2 闭包中的this

之前曾经提到过,一个函数被调用时,会自动取得两个特殊变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止。因此永远不可能直接访问外部函数中的这两个变量。

闭包中的this指向全局

如果想访问外层中的this或arguments变量,可以在闭包内让一个变量指向this或argument。这时,新的变量储存在外层的活动对象中,那内部的闭包自然就可以访问了。

注意理解闭包的定义:可以访问另外一个函数作用域中的变量的函数

me是obj1中的活动对象

7.2.3. 内存泄漏

如果一个闭包的作用域链中保存着HTML元素,那么这个元素将无法被摧毁。

局部变量本来应该在函数退出的时候被解除引用,但如果局部变量被封闭在闭包形成的环境中,那么这个局部变量就能一直生存下去。从这个意义上看,闭包的确会使一些数据无法被及时销毁。使用闭包的一部分原因是我们选择主动把一些变量封存在闭包中,因为可能在以后还需要使用这些变量,把这些变量放在闭包中和放在全局作用域,对内存方面的影响是一致的,这里并不能说成是内存泄露。如果在将来需要回收这些变量,我们可以手动把这些变量设为null。

跟闭包和内存泄露有关系的地方是,使用闭包的同时比较容易形成循环引用,如果闭包的作用域链中保存着一些DOM节点,这时候就有可能造成内存泄露。但这本身并非闭包的问题,也并非JavaScript的问题。在IE浏览器中,由于BOM和DOM中的对象是使用C++以COM对象的方式实现的,而COM对象的垃圾收集机制采用的是引用计数策略。在基于引用计数策略的垃圾回收机制中,如果两个对象之间形成了循环引用,那么这两个对象都无法被回收,但循环引用造成的内存泄露在本质上也不是闭包造成的。

Javascript 的垃圾回收机制,我现在知道的有两种:标记、计数。

标记清除:主流策略,并且与此问题无关。

引用计数:容易在循环引用时出现问题的策略。因为计数记录的是被引用的次数,所以循环引用时计数并不会消除。导致无法释放内存。


7.3模仿块级作用域

我们都知道,js中没有块级作用域的概念,这意味着块语句中定义的变量,实际上是在包含函数中而非语句中创建的。

很明显的,即便for循环结束了,i并没有被销毁

上面的例子很明显说明了变量是定义在函数内而不是块作用域内的。因此,如果你想重复定义一个变量,js肯定是不会理你的。

实际运行时,第二个定义被忽略了

但是如果想使用块级作用域,通过闭包也还是可以实现的:

定义方式为:在以function开头的一段代码中,js将其识别为函数声明,根据我们之前所知,函数声明后不能跟(),但是函数表达式后面可以跟小括号。

因此,只需要用(function(){})便可以完成从函数声明 -> 函数表达式的转换。此时再加一对小括号,使其称为自执行函数。

闭包模拟块作用域-立即执行一个函数表达式。
在闭包外i不能被调用了

这个原理其实也很简单,再复习一遍,变量是定义在函数内的。在函数的执行结束后,其内部活动对象会被销毁:因此当闭包运行结束后,它就被销毁了。

它的使用场景通常是在全局环境中使用,目的是不向全局环境内声明太多全局变量。这样我们就不用担心搞乱全局作用域了。


7.5章节小结

你可能感兴趣的:(2020-04-29: 第七章:关于this对象)