【问题标题】:Explanation needed : Cannot understand javascript returning a function需要解释:无法理解返回函数的 javascript
【发布时间】:2015-02-18 12:28:07
【问题描述】:

我更像是一名 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]。

如果有人向我解释这一点,我将不胜感激。 谢谢

【问题讨论】:

    标签: javascript function window closures


    【解决方案1】:

    这是书中的一个错误。他们试图展示使用其他不必要的函数范围来允许内联函数围绕外部范围中的变量关闭的糟糕(性能方面)模式,因为它没有在其他任何地方引用,所以变成了一种私有内联函数引用的变量。如果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/

    在本书的代码中,成为onclick 处理程序的内联函数不会在任何东西周围关闭,而不是在外部范围内关闭函数参数i。相反,在alert() 调用中用作参数的e 变量绑定到内联函数的函数参数e(这就是不发生闭包的原因;闭包仅在函数范围内的变量引用时发生无法绑定到范围内的任何本地,而是绑定到外部范围内的变量)。因为函数最终充当事件处理程序,所以其参数 e 设置为等于启动回调的 Event 对象(如果发生以及何时发生),这就是您在警报消息中看到的原因。

    【讨论】:

      【解决方案2】:

      您应该意识到,在第 5-9 行 (顺便说一句,7 号在哪里?:)) 创建了一个新函数,该函数将绑定为 onclick 的事件侦听器函数。

      见第 9 行:

      }(i); 
      

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

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

      【讨论】:

        【解决方案3】:

        我尝试使用它并在我的 浏览器

        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

        【讨论】:

          猜你喜欢
          • 2012-11-21
          • 1970-01-01
          • 1970-01-01
          • 2013-03-25
          • 2018-02-09
          • 1970-01-01
          • 2021-11-24
          • 1970-01-01
          • 2015-07-10
          相关资源
          最近更新 更多