for (var i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}
给出
6
6
6
6
6
但是使用像这样的IIFE
for (var i=1; i<=5; i++) {
(function(){
var j = i;
setTimeout( function timer(){
console.log( j );
}, j*1000 );
})();
}
给出
1
2
3
4
5
我的问题:为什么没有
for (var i=1; i<=5; i++) {
setTimeout( function timer(){
var j = i;
console.log( j );
}, i*1000 );
}
或
for (var i=1; i<=5; i++) {
function timer() {
var j = i;
console.log(j);
}
setTimeout(timer, i*1000 );
}
像IIFE一样工作吗?在我看来,他们都有一个function
声明,其中包含一个新变量j
,不会创建一个新的词法范围,其中包含i
的特定设置?
答案 0 :(得分:4)
IIFE的重要部分是它立即运行 ;在title_pattern = re.compile(r'.*<title>(.*?)</title>(.*)')
更改之前,它会读取其值并将其放入新变量中。您的其他示例中的i
函数 - i
- 不会立即运行,并且它在新变量中的值是function timer()
已经更改后的值。
此外,在ES6中,您可以i
而不是let i = …
,如果没有IIFE或var i = …
,它将正常工作:
j
因为for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
具有块范围而不是函数范围,并且在let
循环的初始化部分中声明的变量计为在for
块的一半内。
答案 1 :(得分:1)
i
声明的 var
被悬挂。变量不会自动将其范围绑定到内部函数;除非内部函数明确地具有var i
或参数i
(因此定义了绑定到内部函数范围的新i
),{{1将继续引用外部范围中已提升的i
。
例如,如果您愿意,可以按照以下方式执行您的想法:
i
&#13;
(for (var i=1; i<=5; i++) {
setTimeout( function timer(i){
console.log( i );
}, i*1000, i );
}
的第三个参数是函数,第二个参数,将被调用)
这意味着setTimeout
将在迭代期间使用timer
进行调用,并且该函数将使用 new {{1绑定到函数范围的函数,通过参数初始化。
但这是一个非常糟糕的主意 - 更好地使用i
和i
,它们具有块范围而不是函数范围,最好不要遮蔽外部变量。
答案 2 :(得分:0)
这种IIFE
for (var i=1; i<=5; i++) {
(function(){
var j = i;
setTimeout( function timer(){
console.log( j );
}, j*1000 );
})();
}
通常写成
for (var i=1; i<=5; i++) {
(function(j){
setTimeout( function timer(){
console.log( j );
}, j*1000 );
})(i);
}
因此,您可以看到“捕获”值在这种情况下为i
你可以在没有IIFE的情况下做同样的事情
for (var i=1; i<=5; i++) {
function timer(j) {
setTimeout(function() {
console.log(j);
}, j * 1000 );
}
timer(i);
}
当然,这相当于
function timer(j) {
setTimeout(function() {
console.log(j);
}, j * 1000 );
}
for (var i=1; i<=5; i++) {
timer(i);
}
如果使用ES2015 +,您可以使用let
for (let i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}
现在,如果您使用转换器,因为您需要支持ES5(或任何Internet爆炸支持),您将看到转换后的版本
var _loop = function _loop(i) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
};
for (var i = 1; i <= 5; i++) {
_loop(i);
}
看起来非常像以前版本的代码