javascript - javascript 闭包的这种解释正确吗?

标签 javascript closures

对于 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 中创建一个新的作用域,并且函数始终可以访问其祖先作用域。

因此,在第一个示例中,fnPtr 的所有实例都可以从父作用域访问相同的i。单击任意行时,for 循环已完成,i 将为 3。

在第二个示例中,每个返回的 tmp 函数都可以访问传递给工厂函数的 i 参数,该参数在每次迭代/调用时都会有所不同。

关于javascript - javascript 闭包的这种解释正确吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14035317/

相关文章:

javascript - Leaflet Popup GetContent(将米转换为英尺)

常规闭包参数

ios - void 函数中意外的非 void 返回值

javascript - 过渡效果不起作用jquery

javascript - 我可以从 ModalDialog 窗口获取开启器窗口吗?

php - 功能 Mootools 和 Ajax 将日期发布到表单

javascript - 使用具有零宽度lookbehind的正则表达式在JavaScript中分割字符串

scala - 闭包和通用量化

javascript - 如何使这个简单的 javascript 闭包工作

javascript - 如何在同一个对象中调用原型(prototype)函数?