这是立即调用的函数表达式吗?
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
表示的位置的值)。
我是一个 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
表示的位置的值)。