如何解决JavaScript闭包与匿名函数
在JavaScript中所有的功能都关闭在这个解释后但是,我们只对确定这些功能的子集感兴趣,这从理论上讲是很[有趣的。此后,除非另有说明,否则对闭包一词的任何引用都将指代此功能子集。
闭包的简单说明:
- 发挥作用。我们称它为F。
- 列出F的所有变量。
- 变量可以有两种类型:
- 局部变量(绑定变量)
- 非局部变量(自由变量)
- 如果F没有自由变量,则它不能是闭包。
- 如果F具有任何自由变量(在F 父范围中定义),则:
- 必须有其中的F只有一个父范围 自由变量绑定。
- 如果从 ***
- 自由变量称为闭包F的升值。
现在,让我们用它来找出谁使用闭包,谁不使用闭包(为便于说明,我将函数命名为):
for (var i = 0; i < 10; i++) {
(function f() {
var i2 = i;
setTimeout(function g() {
console.log(i2);
}, 1000);
})();
}
在以上程序中,有两个功能:f
和g
。让我们看看它们是否为闭包:
对于f
:
- 列出变量:
- 查找每个自由变量绑定到的父范围:
-
i
被 到了全球范围。 -
setTimeout
被 到了全球范围。 -
console
被 到了全球范围。
-
- 该功能在哪个范围内 ?在 。
- 因此
i
没有 通过f
。 - 因此
setTimeout
没有 通过f
。 - 因此
console
没有 通过f
。
- 因此
因此,该功能f
不是闭包。
对于g
:
- 列出变量:
- 查找每个自由变量绑定到的父范围:
-
console
被 到了全球范围。 -
i2
被 到的范围f
。
-
- 该功能在哪个范围内 ?的 。
- 因此
console
没有 通过g
。 - 因此
i2
被 通过g
。
- 因此
因此,该功能g
是用于自由变量的封闭i2
(这是用于的upvalue g
) 它的 从内setTimeout
。
for (var i = 0; i < 10; i++) {
setTimeout((function f(i2) {
return function g() {
console.log(i2);
};
})(i), 1000);
}
在以上程序中,有两个功能:f
和g
。让我们看看它们是否为闭包:
对于f
:
- 列出变量:
-
i2
是 变量。 -
g
是 变量。 -
console
是一个 变量。
-
- 查找每个自由变量绑定到的父范围:
-
console
被 到了全球范围。
-
- 该功能在哪个范围内 ?在 。
- 因此
console
没有 通过f
。
- 因此
因此,该功能f
不是闭包。
对于g
:
- 列出变量:
- 查找每个自由变量绑定到的父范围:
-
console
被 到了全球范围。 -
i2
被 到的范围f
。
-
- 该功能在哪个范围内 ?的 。
- 因此
console
没有 通过g
。 - 因此
i2
被 通过g
。
- 因此
因此,该功能g
是用于自由变量的封闭i2
(这是用于的upvalue g
) 它的 从内setTimeout
。
因此,您和您的朋友都在使用闭包。别吵了 我希望我清除了闭包的概念以及如何为你们两个人识别它们。
首先让我们考虑以下程序(它是control):
lexicalScope();
function lexicalScope() {
var message = "This is the control. You should be able to see this message being alerted.";
regularFunction();
function regularFunction() {
alert(eval("message"));
}
}
- 我们知道,无论
lexicalScope
和regularFunction
不封闭 。 - 当我们执行程序时,
message
收到警告,regularFunction
它不是闭包的(即它可以访问其父作用域中的 变量-包括message
)。 - 当我们执行程序时, 到
message
确实确实有警报。
接下来让我们考虑以下程序(这是替代程序):
var closureFunction = lexicalScope();
closureFunction();
function lexicalScope() {
var message = "This is the alternative. If you see this message being alerted then in means that every function in JavaScript is a closure.";
return function closureFunction() {
alert(eval("message"));
};
}
- 我们知道,这只是 *
- 当我们执行程序时, 我们希望*
message
不会closureFunction
闭包而收到警告(即,在 它只能访问其所有 (请参见此答案)-不包括)。 *message
- 当我们执行程序时, 到
message
实际上正在被警告。
我们从中得出什么呢?
- JavaScript解释器对待闭包的方式与对待其他函数的方式没有区别。
- 每个功能都带有其作用域链。闭包没有 引用环境。
- 闭包就像其他函数一样。当在它们所属的范围 之外* 的范围中 它们时,我们只称它们为闭包, 这是一个有趣的情况。 ***
解决方法
我的一个朋友和我目前正在讨论JS中的闭包和不闭包。我们只想确保我们正确理解它。
让我们来看这个例子。我们有一个计数循环,希望延迟在控制台上打印计数器变量。因此,我们使用setTimeout
和 闭包
捕获计数器变量的值,以确保其不会打印N倍于值N的值。
没有 闭包 或接近 闭包 的错误解决方案是:
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
},1000);
}
当然,它将i
在循环后输出10倍的值,即10。
所以他的尝试是:
for(var i = 0; i < 10; i++) {
(function(){
var i2 = i;
setTimeout(function(){
console.log(i2);
},1000)
})();
}
按预期打印0到9。
我告诉他,他并没有使用 闭包 捕获i
,但他坚持认为自己是。我通过将for循环体放在另一个循环中(将他的匿名函数传递给),再次打印10次10
证明了他没有使用 闭包 。如果我将他的函数存储在a中并在循环 后 执行它,也打印10次10,则同样适用。所以我的观点是 他并没有真正
捕获 的值 ,因此他的版本 不是 闭包的。setTimeout``setTimeout``var
__i
我的尝试是:
for(var i = 0; i < 10; i++) {
setTimeout((function(i2){
return function() {
console.log(i2);
}
})(i),1000);
}
所以我捕获了i
(i2
在闭包中命名),但是现在我 返回了 另一个函数并传递了它。
就我而言,传递给setTimeout的函数实际上捕获了i
。
现在谁在使用闭包,谁没有?
请注意,这两种解决方案在控制台上都延迟输出0到9,因此它们可以解决原始问题,但是我们想了解这两种解决方案中的哪一种 使用闭包 来完成此任务。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。