This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center
                            
                        
                    
                
                                7年前关闭。
            
                    
对于tl; dr,在为表中的行创建单击处理程序时,使用闭包使函数指向内存中的相同位置,而不是每次都像下面的代码一样指向不同的位置。

除此以外:

我正在学习javascript,我想我了解闭包是什么以及为什么有用。这是我的理由;这是对的吗?

对于HTML表格,即使我单击第一行或第二行,下面的代码也始终显示被单击的最后一行。我的推理是代码创建3个不同的堆栈帧,每个i分别等于0、1和2。由于2是最近的堆栈帧,因此fnPtr的返回值指向2。

var table = document.getElementById("tableid3");
var rows = table.getElementsByTagName("tr");
for (var i = 0; i < rows.length; i++) {
    var curRow = table.rows[i];
    //get cell data from first col of row
    var cell = curRow.getElementsByTagName("td")[0];
    var fnPtr = function() {
        alert("row " + i + " data="+ cell.innerHTML);
    }
curRow.onclick = fnPtr;
}


现在,下面的代码(来自一个SO问题)使用闭包并仅创建一个堆栈框架,即createfunc()的框架。但是在此框架内部是局部变量tmp,它指向匿名函数。当用0、1和2调用createfunc()时,返回值指向相同的堆栈框架(createfunc()的堆栈框架内的堆栈框架),这意味着未创建3个堆栈框架。每次返回createfunc()时,返回值插槽中的值都指向内存中的相同位置,而不是每次都像上面的代码一样位于不同的位置。

function createfunc(i) {
    var tmp = function() { console.log("My value: " + i); };
    console.log(tmp);
    return tmp;
}
for (var i = 0; i < 3; i++) {
    funcs[i] = createfunc(i);
}
for (var j = 0; j < 3; j++) {
    funcs[j]();                        // and now let's run each one to see
}


我了解封包如何工作吗?

最佳答案

我不确定以堆栈框架的方式考虑javascript的工作方式是一个好主意-javascript太高级了。

在第一个代码段中,您创建的fnPtr函数对象捕获实际变量(但尚未获取其值),因此,如果该变量以后发生更改,则在调用该函数时,当前时间的i变量值用来。您的循环可能创建了100个fnPtr函数对象,但是每个对象都拥有对完全相同的i变量的引用。

第二个片段利用了以下事实:当您将原始值(例如数字)作为函数参数传递给函数时,javascript会创建它的副本。因此,每次调用createfunc时,都会创建该变量的新副本,并且将此新变量的值设置为调用createfunc时参数具有的任何值。我强调的事实是,这是一个新变量,并且没有其他函数持有对该变量的引用。因此,当您的createfunc返回一个新函数时,该新函数将保留对已复制的该新互斥i变量的引用。

10-05 20:53