这是立即调用的函数表达式吗?

Is this an immediately invoked function expression?

我是一个 javascript 新手,正在尝试了解这段代码。 我在这里 http://brackets.clementng.me/post/24150213014/example-of-a-javascript-closure-settimeout-inside

我还是很难理解。因为它涉及一些我不熟悉的模式。

// output 0-9, seperated by 1 sec delay.
for (var i = 0; i < 10; i++) {
    setTimeout(function(x) { 
        return function() { 
            console.log(x); 
        }; 
    }(i), 1000*i);
}

这段代码中(i)是什么意思?

function(x) { 
    return function() { 
        console.log(x); 
    }; 
}(i)

我以为是立即调用的函数表达式。 但这不是正确的语法是:

(function() {
  // some code
})();

是的,(i) 是调用的参数列表。查看 here 以获得详细说明。在这种情况下,分组括号是不必要的,因为它是 setTimeout 函数调用的参数,因此无论如何都是一个表达式。

术语 IIFE 不仅仅指这种模式的语句形式,其中 parenthesis would be necessary.

在您的立即调用函数示例中,括号是可选的。

(function() {
  // some code
})();

可以重写为

function() {
  // some code
}();

因此示例函数调用中的 i 成为函数定义中的 x

function(x) { // x = 1
    return function() { 
        console.log(x); // x = 1
    }; 
}(1)

这确实是一个 IIFE。您引用的语法是 0 个参数的 IIFE;您询问的语法是 1 个参数的 IIFE。它将在内部代码中将 i 赋值给 x。比较:

var print0 = function() {
  console.log("Hello!");
};
print0();

(孤立地)等同于

(function() {
  console.log("Hello!");
})();

因此得名:您创建一个函数,然后立即调用它。

然而,如果你想要一个论点,没有任何改变:

var print1 = function(name) {
  console.log("Hello, " + name);
};
print1("George");

(孤立地)等同于

(function(name) {
  console.log("Hello, " + name);
})("George");

此处的括号确保函数定义将被视为表达式而不是语句。还有其他方法可以确保这一点,常见的方法是

!function() {
  console.log("Hello!");
}();

(但有理由更喜欢括号。)由于您将它用作 setTimeout 调用的参数,它不可能是一个语句,因此这些 hack 是没有必要的。它仍被称为 "immediately invoked function expression",因为您仍在构建函数表达式并立即调用它。

这里使用IIFE的原因是为了"capture"变量i的值,而不是x的位置。如果没有闭包技巧,您将获得 10 次超时,全部输出 10(当 console.log 解析时由 x 表示的位置的值)。