setInterval() **调用的函数如何在封闭函数 returns 之后访问封闭函数的变量?
How does the function **called by** setInterval() access the variables of the enclosing function, after the enclosing function returns?
我对Javascript的理解是,一旦函数完成其工作,该函数的局部变量就会被丢弃。但是,请考虑以下代码:
document.onkeydown = function Encloser(evt){
evt = evt || window.event;
switch(evt.keyCode){
case 88:
var x = 50;
var intrvl = setInterval(function Enclozee(){
console.log(x);
ctx.clearRect(0, 0, cnv.width, cnv.height);
actionRoutine(x--);
if(x < 0)
clearInterval(intrvl);
}, 50);
break;
}
// Redraw Routine
console.log(evt.keyCode);
ctx.clearRect(0, 0, cnv.width, cnv.height);
actionRoutine(50);
console.log("returning now");
};
每 50 毫秒调用一次的 Enclozee
从内部访问变量 x
和 intrvl
,但是这些操作在 Encloser
返回后很久才发生(通过在控制台上记录 returning now
)。这怎么可能? Encloser
是否让垃圾收集器等待?这种行为不安全吗?以及如何在 Encloser
函数 returns 之后将基本类型 x
从函数堆栈中移除?
这个概念被称为“闭包”。虽然有些语言会在调用堆栈完成时擦除所有局部变量,但 javascript 不是其中之一。只要存在从内存根到该变量的路由,变量就不会被垃圾回收。
因此,只要某些东西仍然引用该内部函数,就不会收集内部函数使用的任何变量。在这种情况下,是 setInterval 的内部代码保留了对内部函数的引用,并且它将继续这样做,直到您调用 clearInterval。在那之后,不再有对该函数的引用,因此它可以与它引用的变量一起被垃圾回收。
很安全
这是因为在创建 Enclozee
时,它还会创建一个 闭包 ,允许它访问在其创建时范围内的所有变量创建,即使在其原始上下文结束后
您可以在此处阅读更多相关信息 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
我对Javascript的理解是,一旦函数完成其工作,该函数的局部变量就会被丢弃。但是,请考虑以下代码:
document.onkeydown = function Encloser(evt){
evt = evt || window.event;
switch(evt.keyCode){
case 88:
var x = 50;
var intrvl = setInterval(function Enclozee(){
console.log(x);
ctx.clearRect(0, 0, cnv.width, cnv.height);
actionRoutine(x--);
if(x < 0)
clearInterval(intrvl);
}, 50);
break;
}
// Redraw Routine
console.log(evt.keyCode);
ctx.clearRect(0, 0, cnv.width, cnv.height);
actionRoutine(50);
console.log("returning now");
};
每 50 毫秒调用一次的 Enclozee
从内部访问变量 x
和 intrvl
,但是这些操作在 Encloser
返回后很久才发生(通过在控制台上记录 returning now
)。这怎么可能? Encloser
是否让垃圾收集器等待?这种行为不安全吗?以及如何在 Encloser
函数 returns 之后将基本类型 x
从函数堆栈中移除?
这个概念被称为“闭包”。虽然有些语言会在调用堆栈完成时擦除所有局部变量,但 javascript 不是其中之一。只要存在从内存根到该变量的路由,变量就不会被垃圾回收。
因此,只要某些东西仍然引用该内部函数,就不会收集内部函数使用的任何变量。在这种情况下,是 setInterval 的内部代码保留了对内部函数的引用,并且它将继续这样做,直到您调用 clearInterval。在那之后,不再有对该函数的引用,因此它可以与它引用的变量一起被垃圾回收。
很安全
这是因为在创建 Enclozee
时,它还会创建一个 闭包 ,允许它访问在其创建时范围内的所有变量创建,即使在其原始上下文结束后
您可以在此处阅读更多相关信息 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures