【问题标题】:javascript closure Immediately Invoked Function Expressionjavascript 闭包立即调用函数表达式
【发布时间】:2016-01-05 11:43:17
【问题描述】:

我正在尝试更深入地了解 javascript 闭包,阅读有关主题的文章,我遇到了许多与以下函数类似的示例:

function idCreator(listOfItems) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < listOfItems.length; i++) {
        listOfItems[i]["id"] = function (j) { 

            return function () {
                return uniqueID + j;
            }()
        }
        (i); 
    }
    return listOfItems;
}

我理解使用 IIFE 内部函数并将计数器变量作为参数传递的主要概念,因此例如在上面的示例中,我们将返回正确的 i (index) ,而不是我们在结束后得到的值循环。

我的问题是为什么返回一个匿名函数,返回值本身的工作原理不一样吗?

类似:

function iDCreator(listOfItems) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < listOfItems.length; i++) {
        listOfItems[i]["id"] = function (j) { 
                return uniqueID + j;
        }
        (i); 
    }
    return listOfItems;
}

【问题讨论】:

    标签: javascript closures


    【解决方案1】:

    我看到在您提供的示例中使用闭包和 IIFE 的唯一原因是教学:展示如何使用 IIFE 交换代码并获得完全相同的结果。此外,它还展示了内部函数如何仍然可以访问外部变量。

    正如 Quentin 所说,在这个例子中,没有其他合乎逻辑的理由使用闭包和 IIFE。它甚至会适得其反(降低性能并混淆代码)。

    通过“定义”,以后不会调用 IIFE(“立即调用”)。它的主要(也可能是唯一的)用途是提供函数作用域/闭包(就好像它是提供块作用域的其他语言中的“块”一样),同时仍然避免必须使用正常的函数声明,您必须在其中选择一个标识符,它可能与在其他地方定义的另一个标识符发生冲突。

    // Normal function declaration:
    function someIdentifier() {}
    // Let's immediately call it to execute the code.
    someIdentifier();
    // what happens if "someIdentifier" was defined somewhere else?
    // For example in a previous loop iteration?
    

    这就是作者必须在其 for 循环中使用 IIFE 的原因。

    在作用域/闭包内,您可以使用所需的任何标识符(用于变量和函数声明),同时防止与作用域外的标识符发生任何冲突。无论是使用函数声明、函数表达式还是 IIFE。

    // Using an Immediately Invoked Function Expression:
    (function idForRecursion() { // being a Function Expression rather than a declaration, you can even use an identifier here to be used for recursion, and it will not pollute the global scope.
    
        var anyIdentifier;
        // If "anyIdentifier" were defined outside, this local definition will "shadow" it for the current closure only, without affecting / polluting the outside definition and value.
    
        // As in normal closures, you can still access variables outside the IIFE.
        alert(myGlobalVar);
    })();
    

    因此,关于闭包的一个更具教学意义的示例可能是一个 IIFE,其中 uniqueID 在内部并递增但在全局范围内隐藏(通过闭包),因此没有人可以摆弄/干扰它:

    var iDCreator = (function () {
        var uniqueID = 100; // initial value.
    
        return function innerFn(listOfItems) {
            for (var i = 0; i < listOfItems.length; i += 1) {
                listOfItems[i]["id"] = uniqueID;
                uniqueID += 1;
            }
            return listOfItems;
        };
    })(); // "iDCreator" is now a reference to the "innerFn" which has a closure with "uniqueID", but the latter is not accessible from global scope.
    // Calling "iDCreator" several times gives truly unique id's, incremented from the previous call.
    

    【讨论】:

      【解决方案2】:

      根本不需要使用函数。

      for (i = 0; i < listOfItems.length; i++) {
          listOfItems[i]["id"] = uniqueID + i;
      }
      

      当您分配稍后将调用的函数时,使用闭包可能很有用。它不在这里。看起来代码的作者刚刚走神了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 2017-08-30
        • 2012-09-02
        • 2018-01-07
        • 2012-12-28
        • 2017-04-06
        • 2014-08-10
        相关资源
        最近更新 更多