为什么不鼓励在JavaScript循环中创建函数?

时间:2017-01-18 03:44:04

标签: javascript html

我是一个绝对的新手,我只是在 JavaScript:好的部分中读到这个。

在讨论范围的章节中,它说“重要的是要理解内部函数可以访问外部函数的实际变量而不是副本以避免以下问题。 “然后以下两个示例如下所示:

// BAD EXAMPLE

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

// END BAD EXAMPLE

href='myscheme://mypackage.com' onclick='javascript:gotonextpagefunction();'

根据作者的说法,第二个例子更好,因为它不在函数内部使用循环,否则它可能是计算上的浪费。但我很茫然,不知道如何处理它们。我如何将他的理论应用于实际应用中?任何人都可以说明这两个结合HTML的例子吗?

5 个答案:

答案 0 :(得分:6)

问题在于关闭。内部函数可以访问在这些函数之外定义的变量i。在执行循环的所有迭代之后,变量i将保持nodes.length的值。因此,当您点击nodes[0]时,提醒会显示nodes.length,这不是您所期望的。 (您可能希望警报说出0。)点击nodes[1]nodes[2]等时同样如此。所有人的提醒都会显示nodes.length

答案 1 :(得分:1)

您可以在此处使用HTML进行检查:https://jsfiddle.net/vdrr4519/

&#39; multifunc&#39;元素以具有许多功能的例子为单位,“单一功能” - 具有单个功能。请参阅,我们将所有元素与类一起使用并将它们传递给函数。

multifunc(document.querySelectorAll('.multifunc'));

功能运行&#39;用于&#39;循环并添加“点击”#39;事件监听器。因此元素应该在点击时提醒其索引(从0开始)。但是在具有许多功能的示例中,产生了错误的值(由于关闭,其他答案也突出了该问题)。

我想我也应该说它不是单一功能/多功能的问题 - 这是一个使用闭包的问题。你看,我可以实现一个包含许多闭包的工作示例:https://jsfiddle.net/pr7gqtdr/1/。我基本上和你在单功能处理程序中所做的一样,但是每次调用新的帮助程序&#39;功能:

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

请注意,最后这个(i)是一个立即函数调用,因此onclick获取一个函数,其中i变量设置为闭包。

但是,单功能选项更好一点,因为它的内存效率更高,我猜。功能是对象。如果您创建了许多内容,通常会占用更多内存。因此,从这些中选择,我会坚持使用&#39;处理程序&#39;功能选项。

答案 2 :(得分:0)

糟糕的例子创建了许多事件处理程序;每个活动一个。这个好的例子创建了一个单独的事件处理程序并将其分配给所有事件。

有了这个坏例子,你已经创建了许多单独的函数,而不仅仅是一个。这可能是很多额外的开销和很多潜在的范围问题。这些包括闭包问题,例如仅为循环中的最后一项触发的事件。

此外,这个好例子可让您更轻松地取消订阅事件,因为您可以访问原始函数指针。

这个好例子也更容易阅读和理解。循环仅用于创建元素并绑定其事件;这些事件的处理在其他地方完成。

答案 3 :(得分:0)

正如Soviut所提到的,你在这个坏榜样中创造了许多事件处理程序。此外,重要的是要指出错误的示例函数引用相同的i变量,这意味着它们执行时所有这些变量的最后一个值都为nodes.length

这是因为创建了一个闭包。您可以在 Closures 中阅读更多相关信息。

答案 4 :(得分:0)

首先,在坏例子中,为每个事件处理程序创建一个函数;循环创建多个函数对象。而在第二个示例中,创建单个函数并从循环内部引用。所以你节省了大量的内存。

其次,在坏例子中,当“i”的值运行时,该函数不保留该值,并且当它运行时,它将始终返回“i”的最后一个值。然而,在一个好的例子中,当“i”被传递给函数时,该值被保留为函数的词法环境,并且当它被调用时,它将返回正确的值。

第三,正如@Gary Hayes所提到的,我们可能也想在其他地方使用这个功能。所以最好让它独立于循环。