需要说明:无法理解javascript返回函数

时间:2015-02-18 12:28:08

标签: javascript function window closures

我更像是一名C ++ / Java程序员,而且是Javascript的新手。我一直在阅读Javascript这本好的部分书。在关于函数的章节中,作者引用了一个例子,通过执行以下操作将事件监听器附加到DOM中的节点

     // When you click on a node, an alert box will display the ordinal of the node.

1 var add_the_handlers = function (nodes) {
2        var i;
3        for (i = 0; i < nodes.length; i += 1) {
4            nodes[i].onclick = function (i) {
5                return function (e) {
6                    alert(e);
7                };
8            }(i);
9        
10 };

上述功能的目的是为DOM中的所有节点添加onclick事件处理程序,以便在单击任何节点时,它会提醒分配给它或其序号的编号。

我无法理解第5行到第8行。我知道函数(onclick = function(i) ...)会立即以i为参数调用。但是这个'i'如何传递给正在返回的函数? 'e'如何获得后来被警告的'i'的价值?

我尝试使用它并在浏览器中运行以下代码

window.onclick = function(i){
    return function(e){
        console.log("Inner function called");
        alert(e);
    }
}(4); 

我预计会有一个数字为4的警告窗口。相反,警报窗口显示[object MouseEvent]。

如果有人向我解释,我真的很感激。 感谢

3 个答案:

答案 0 :(得分:2)

这本书中的错误。他们试图展示使用其他不必要的函数作用域来允许内联函数围绕外部作用域中的变量进行闭包的可怕(性能方面)模式,因为它在其他任何地方都没有引用,因此变成了一种私有内联函数引用的变量。如果i变量确实用作alert()调用的参数,则代码将起作用:

var add_the_handlers = function(nodes) {
    for (var i = 0; i < nodes.length; ++i) {
        nodes[i].onclick = function(i) {
            return function() {
                alert(i);
            };
        }(i);
    } // end for
};

add_the_handlers(document.getElementsByTagName('div'));

http://jsfiddle.net/pzht9mLu/

在本书的代码中,不是围绕外部作用域中的函数参数i进行闭包,而是成为onclick处理程序的内联函数不会关闭任何内容 。相反,在e调用中用作参数的alert()变量绑定到内联函数的函数参数e(这就是为什么没有发生闭包;闭包只发生在函数作用域内的变量引用无法绑定到作用域内的任何局部,而是绑定到外部作用域中的变量。因为该函数最终用作事件处理程序,所以它的参数e设置为等于启动回调的Event对象(如果它发生的话),这就是你在警报中看到的那个原因消息。

答案 1 :(得分:0)

您应该意识到的是,在第5-9行(其中数字为7 btw?:))创建了一个新函数,该函数将被绑定为onclick的事件监听器函数。 / p>

见第9行:

}(i); 

这意味着立即调用上面的函数,传入i作为其函数参数,然后返回一个新函数。

例如,如果您在此内部函数中使用i的值,它将在闭包中捕获,因此onclick函数将可以访问它,即使它是从完全不同的范围调用的。

答案 2 :(得分:0)

  

我试着玩它并在我的脑子里运行以下代码   浏览器

window.onclick = function(i){
    return function(e){
        console.log("Inner function called");
        alert(e);
} }(4);
     

我预计会有一个数字为4的警告窗口。相反,警报窗口显示[object MouseEvent]。

从不使用参数i。警报产生e,这是onclick事件处理程序的参数。哪个是MouseEvent对象。

var add_the_handlers = function (nodes) {
var i;
for (i = 0; i < nodes.length; i += 1) {
    nodes[i].onclick = function (i) {
        return function (e) {
            alert(e);
        };
     }(i);
};
     

上述功能的目的是添加一个onclick事件处理程序   DOM中的所有节点,当任何节点都是时   点击它会提醒分配给它或其序号的号码。

     

我无法理解第5到第8行。我明白了   函数(onclick = function(i)...)立即用i调用   作为其论点。但是这个'我'是如何传递给那个功能的呢?   正在退货? 'e'如何获得后来的'i'的价值   被警告?

i未传递给第二个函数,并且您的当前代码永远不会显示。你现在正在做的事实上没有什么不同:

nodes[i].onclick = function (e) { alert(e); };

如果您要生成包含正确值i的提醒,则只需使用原始代码,但提醒i而不是e