JavaScript闭包-函数作用域
我有一个关于JavaScript闭包的问题,特别是在调用(内部)函数时的范围。JavaScript闭包-函数作用域,javascript,browser,memory-leaks,scope,closures,Javascript,Browser,Memory Leaks,Scope,Closures,我有一个关于JavaScript闭包的问题,特别是在调用(内部)函数时的范围。 这个问题还与浏览器内存泄漏有关,我们将看到 首先对我的问题做一个“简短”的介绍: 因此,我知道当调用函数时,它会进入执行上下文(添加在调用堆栈顶部)。创建一个“激活对象”,其中包含所有局部变量、函数的arguments对象和添加到其中的参数(作为属性) 由于内部函数可以访问封闭函数的变量——即使内部函数在其封闭函数的执行结束后被调用——因此必须对“free”(=外部)变量进行一些引用。这由范围链管理,范围链也添加到执
这个问题还与浏览器内存泄漏有关,我们将看到 首先对我的问题做一个“简短”的介绍: 因此,我知道当调用函数时,它会进入执行上下文(添加在调用堆栈顶部)。创建一个“激活对象”,其中包含所有局部变量、函数的arguments对象和添加到其中的参数(作为属性) 由于内部函数可以访问封闭函数的变量——即使内部函数在其封闭函数的执行结束后被调用——因此必须对“free”(=外部)变量进行一些引用。这由范围链管理,范围链也添加到执行上下文中 根据,执行上下文的作用域由列表顶部的实际激活对象组成,该列表隐藏保存在函数本身上: 范围由对象列表(或链)组成。每个函数对象都有一个内部[[scope]]属性[…]分配给函数调用的执行上下文的范围由相应函数对象的[[scope]]属性所引用的列表组成,激活对象添加在链的前面(或列表的顶部) 这是完全合乎逻辑的,因为由于这个内部作用域属性,存在对自由变量的引用,因此首先闭包能够到达变量(通过作用域链),其次它防止垃圾收集器在封闭函数的执行结束时释放相关的内存 简言之:作用域链(包括函数的内部作用域属性)是闭包如此工作的原因
现在具体地回答我的问题: 哪些变量被添加到函数的内部作用域属性? 据我所知,以下部分: 闭包是函数和声明该函数的词汇环境的组合。此环境由创建闭包时范围内的任何局部变量组成 。。。这意味着在形成闭包时,对所有局部变量的引用都将添加到内部范围属性中 当闭包没有使用其封闭函数中的所有局部变量时,这似乎有点不必要,但没有关系;真正的问题是,这将导致内存泄漏,我们将在下面看到 考虑以下代码(这是对的一小部分缩减,我们将在后面讨论): 在replace的第一次函数调用之后,将发生以下情况:
- 优先级=空
- 对包含以下属性的新对象(比如地址为0x01)的字符串引用:
- 1MB对象
- 函数someMethod,其内部scope属性引用了封闭函数的所有局部变量,这意味着也引用了priothing,它为null
- priothing=对地址为0x01的对象的引用
- 对包含以下属性的新对象(比如地址为0x02)的字符串引用:
- 1MB对象
- 函数someMethod,其内部作用域属性引用了priothing(地址为0x01)
- priorThing本身指向具有相同结构的对象
好的,现在简单总结一下:
- 是否在闭包的作用域中引用了所有局部变量?()
- 因为内存泄漏,这将是最糟糕的
- 如果任何闭包使用变量,所有闭包都引用变量吗?()
- 这是最好的,因为可以避免内存泄漏——但是如果程序员没有意识到这种行为,可能会发生错误
- 还是每个闭包都有自己的引用,这取决于它们自己使用的变量?
- 将完全避免内存泄漏,但需要更多的内存,因为每个闭包都必须有自己的“词汇环境”对象(由内部scope属性引用)
eval
时也会发生这种情况,这可能会引用变量。“如果有任何闭包使用它,所有闭包都引用这些变量吗?”-是的,这是一些实现作为优化所做的,但它不会导致错误,因为它是完全透明的。“或者每个闭包都有自己的引用,这取决于它们自己使用的变量?”-不,闭包的作用域是共享的。“都是局部变量吗?”
var theThing = null;
var replaceThing = function () {
var priorThing = theThing; // hold on to the prior thing
theThing = {
longStr: new Array(1000000).join('*'), // create a 1MB object
someMethod: function () {
console.log("someMessage");
}
};
};
setInterval(replaceThing, 1000); // invoke `replaceThing' once every second