Open yxfanxiao opened 8 years ago
想起了之前遇到的一题,现在豁然开朗:
!function () {
for (var i = 0; i < 5; i++) {
!function () {
setTimeout(function () {
console.log(i) // 5 5 5 5 5
}, 1000)
}()
}
}()
!function () {
for (var i = 0; i < 5; i++) {
var a = i;
!function () {
setTimeout(function () {
console.log(a) // 4 4 4 4 4
}, 1000)
}()
}
}()
!function () {
for (var i = 0; i < 5; i++) {
!function (i) {
setTimeout(function () {
console.log(i) // 0 1 2 3 4
}, 1000)
}(i)
}
}()
我执行了这么一段代码:
!function () {
for (var i = 0; i < 5000000000000; i++) {
!function () {
setTimeout(function () {
console.log(i)
}, 1000)
}()
}
}()
结果如图: 没过一会,node监测到内存占用过高,就停止了程序。
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
我的理解是:异步的setTimeout,导致了所有匿名函数都是被引用状态,所有AO保存在内存之中,因此内存占用飙升。
/* 2015-9-21 update */ 看到一篇讲的很好的 https://cnodejs.org/topic/5599521293cb46f578f0a57e
// 修改了很多次,最后把我个人目前的理解通俗地记录下来,有错请留言指正!
函数第一次被调用分为2个阶段,函数创建和函数激活。之后被调用就只进行函数激活。 当某个函数被第一次调用时,先进行函数创建。 首先介绍执行环境(也称执行上下文)的概念:指的是js在执行过程中可以取到哪些变量、函数。由于js是单线程的,当进入一个新的函数时,会产生一个新的上下文(context),被压入js的上下文堆栈中,等到函数执行完毕后弹出。
变量对象:是一个与执行上下文相关联的特殊对象。 全局变量自身就是变量对象,只有全局上下文的变量对象才能间接地引用变量(浏览器中window,node中global且 VO === this === global)。 但是函数的变量对象无法直接引用VO,并且它扮演的角色叫作活动对象(Activation object且VO ===AO)。当函数被激活时,arguments和formal parameters are added。
作用域链:先把parent scopes 赋值给function的一个内部变量[[scope]],然后把被arguments和形参绑定后的 VO|AO 压入Scope Chain最前端,之后是按顺序的 parent scopes。(保证了取参和取函数的顺序) 之后,当函数执行完成时,执行环境中的作用域链销毁。若没有取消对函数的引用,
AO活动对象作用域链(AO+[[scope]])会一直存在内存之中。// 这里我困扰了很久,求指正。PS:书(js高级程序设计第三版P.180 11行)上写的是:只有AO存在 // 内存之中。 // 现在的理解是:函数的[[scope]]是在函数创建时就赋给它的,属于函数的静态属性,而作用域链 // 是由AO+[[scope]]组成的,这里的[[scope]]是类似指针的引用,因此不算占用内存。但是我更偏 // 向于作用域链留在内存之中。
当再次激活已创建过的函数时,取函数的[[scope]],然后根据新的arguments和形参生成新的AO。
this指向, 举个栗子:
作用域链的顺序, 举个栗子:
来看一段闭包,
当匿名函数从scope()中返回时,它的作用域链被初始化为包含了scope()函数的活动对象和全局变量对象,也就可以访问全局和scope()函数中的变量。并且,当scope()执行完毕,其执行环境的作用域链就被销毁,但是活动对象不会被销毁,依然存在内存中,直到匿名函数被销毁后,scope()的活动对象才会被销毁。 // create 作用域链 // 0: closure AO; // 1:scope() AO // 2: global VO
完。 这是我学习过程中的笔记,若有错误,请指正。 我的个人理解不保证对,所以万一被转载,对误人子弟不负责任。 参考资料: JavaScript高级程序设计(第三版)