Javascript 在封闭函数返回后,**setInterval()调用的函数**如何访问封闭函数的变量?

Javascript 在封闭函数返回后,**setInterval()调用的函数**如何访问封闭函数的变量?,javascript,scope,setinterval,Javascript,Scope,Setinterval,我对Javascript的理解是,一旦函数完成了它的工作,该函数的局部变量就会被丢弃。但是,请考虑下面的代码: document.onkeydown = function Encloser(evt){ evt = evt || window.event; switch(evt.keyCode){ case 88: var x = 50; var intrvl = setInterval(function Encloz

我对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");
};
document.onkeydown=函数封闭器(evt){
evt=evt | | window.event;
开关(evt.keyCode){
案例88:
var x=50;
var intrvl=setInterval(函数Enclozee(){
控制台日志(x);
ctx.clearRect(0,0,cnv.宽度,cnv.高度);
动作程序(x-);
if(x<0)
清除间隔(intrvl);
}, 50);
打破
}
//重画程序
console.log(evt.keyCode);
ctx.clearRect(0,0,cnv.宽度,cnv.高度);
行动程序(50);
console.log(“立即返回”);
};

每隔50ms调用一次的
Enclozee
,从内部访问变量
x
intrvl
,但这些操作在
enclozer
返回后很久才会发生(通过在控制台上记录
立即返回
)。怎么可能呢?
封闭程序是否让垃圾收集器等待?这种行为不安全吗?在
封闭程序
函数返回后,原语类型
x
如何不从函数堆栈中删除?

这个概念称为“闭包”。虽然有些语言在调用堆栈完成时会擦除所有局部变量,但javascript不是其中之一。只要存在从内存根到该变量的路由,变量就不会被垃圾收集


因此,只要有东西仍然引用该内部函数,内部函数使用的任何变量都不会被收集。在本例中,是setInterval的内部代码保留对内部函数的引用,它将继续这样做,直到调用clearInterval为止。在这一点之后,不再有对函数的引用,因此它可以与它引用的变量一起被垃圾收集。

这个概念被称为“闭包”。虽然有些语言在调用堆栈完成时会擦除所有局部变量,但javascript不是其中之一。只要存在从内存根到该变量的路由,变量就不会被垃圾收集

因此,只要有东西仍然引用该内部函数,内部函数使用的任何变量都不会被收集。在本例中,是setInterval的内部代码保留对内部函数的引用,它将继续这样做,直到调用clearInterval为止。在这一点之后,就不再有对函数的引用了,因此它可以与它引用的变量一起被垃圾收集。

这是安全的

这是因为当创建
Enclozee
时,它也会创建一个闭包,允许它访问创建时在其范围内的所有变量,即使在其原始上下文结束后也是如此

您可以在此处阅读更多信息-

它是安全的

这是因为当创建
Enclozee
时,它也会创建一个闭包,允许它访问创建时在其范围内的所有变量,即使在其原始上下文结束后也是如此


您可以在这里了解更多信息-

javascript实现中是否有函数堆栈,或者所有变量(包括原语)是否都进入堆?此外,如果堆栈存在,垃圾收集器是否也会处理堆栈的变量?这取决于浏览器或javascript引擎(我不确定是哪个引擎)来决定在何处分配变量。他们进行了优化,如果可能,将变量分配给堆栈,如果不可能,则分配给堆。作为一名开发人员,您需要知道的是,如果您编写引用变量的代码,它将对您可用(即,在堆上)。您从不使用的变量的情况取决于浏览器。javascript实现中是否有函数堆栈,或者所有变量(包括原语)是否都进入堆?此外,如果堆栈存在,垃圾收集器是否也会处理堆栈的变量?这取决于浏览器或javascript引擎(我不确定是哪个引擎)来决定在何处分配变量。他们进行了优化,如果可能,将变量分配给堆栈,如果不可能,则分配给堆。作为一名开发人员,您需要知道的是,如果您编写引用变量的代码,它将对您可用(即,在堆上)。您从未使用过的变量会发生什么情况取决于浏览器。