我在循环中生成函数时遇到了一些JavaScript问题。
我想要这个工作的方式是for
循环,每次迭代生成一个名为doStuff
+ i
的函数。例如,第一次迭代将生成doStuff1()
,第二次迭代将生成doStuff2()
,依此类推。函数本身(为了示例)只需打印i
- 即doStuff1()
打印1
,doStuff2()
打印2
等。
实际发生了什么,i
并没有“坚持”这个功能。它成为全球范围的一部分或其他东西,所以每个功能都是10。如果您点击下面代码段中的第一个按钮,就可以看到这一点。
在示例二中,我尝试使用function*
表示法来创建正确的函数生成器。我很确定我之前已经实现了它,但我之前从未使用过这种表示法,所以我可能会离开。如果是这种情况,请告诉我。
结果与示例2相同。
例如三,我决定尝试使用字符串而不是整数,它可以工作!对于每次迭代,a
都附加到一个字符串,所以当我按顺序运行生成的函数时,我会得到一个字母a
的小金字塔。
由于我必须在示例3中的不同范围内定义stringOut
变量,所以我决定尝试使用相同的数字(例如4),它再次起作用!这对我来说没有多大意义,因为在更高的范围内,似乎更容易遭受与例1和1相同的问题。 2。
function*
生成器声明?
function test1() {
document.getElementById("output").innerHTML = "#1 Output:";
var myFunctions = [];
for (var i = 0; i < 10; i++) {
myFunctions[i] = function() {
document.getElementById("output").innerHTML += "<br>" + i;
}
}
for (var j = 0; j < 10; j++) {
myFunctions[j]();
}
}
function test2() {
document.getElementById("output").innerHTML = "#2 Output:";
window.test2Funcs = {};
function* Generator() {
var functionName = "doStuff";
var number = 0;
while (number < 10) {
number++;
yield {
myFunction: function() {
document.getElementById("output").innerHTML += "<br>" + number;
},
name: functionName + (number)
}
}
}
var generator = new Generator();
for (var k = 0; k < 10; k++) {
var out = generator.next().value;
window.test2Funcs[out.name] = out.myFunction;
}
for (var l = 1; l < 11; l++) {
func = "doStuff" + l;
test2Funcs[func]();
}
}
function test3() {
document.getElementById("output").innerHTML = "#3 Output:";
var myFunctions = [];
var stringOut = "";
for (var i = 0; i < 10; i++) {
stringOut += "a"; // Edit. Moved from within function below.
myFunctions[i] = function() {
document.getElementById("output").innerHTML += "<br>" + stringOut;
}
}
for (var j = 0; j < 10; j++) {
myFunctions[j]();
}
}
function test4() {
document.getElementById("output").innerHTML = "#4 Output:";
var myFunctions = [];
var numOut = 0; // Edit. Used to be var numOut = "";
for (var i = 0; i < 10; i++) {
numOut++; // Edit. Moved from within function below.
myFunctions[i] = function() {
document.getElementById("output").innerHTML += "<br>" + numOut;
}
}
for (var j = 0; j < 10; j++) {
myFunctions[j]();
}
}
document.getElementById("test1").addEventListener("click", test1);
document.getElementById("test2").addEventListener("click", test2);
document.getElementById("test3").addEventListener("click", test3);
document.getElementById("test4").addEventListener("click", test4);
<button id="test1">1st Attempt</button>
<button id="test2">2nd Attempt</button>
<button id="test3">3rd Attempt</button>
<button id="test4">4th Attempt</button>
<div id="output">
Output:
</div>
答案 0 :(得分:2)
问题是你没有在循环中创建多个函数,它们都是函数的相同实例,共享相同的闭包(包括i
)。调用函数时,i
是退出循环时的值。
var funcs = [];
for (var i=0; i < 5; i++) {
funcs.push(function() {
console.log(i);
});
}
// Here, i is 5
funcs[0](); // 5
funcs[1](); // 5
funcs[4](); // 5
你怎么解决?通过添加一个额外的闭包,我称之为技术&#34;冻结闭合&#34;
function createHandler(val) {
return function() {
console.log(val);
}
}
var funcs = [];
for (var i = 0; i < 5; i++) {
// By calling a different function, a copy of i is passed to that function
funcs.push(createHandler(i));
}
// Here, i is 5
funcs[0](); // 0
funcs[1](); // 1
funcs[4](); // 4
&#13;
您也可以使用Function.bind
var funcs = [];
for (var i = 0; i < 5; i++) {
// By calling bind, a new function is created, with a new closure
funcs.push(
(function(val) {
console.log(val);
}).bind(null, i)
);
}
// Here, i is 5
funcs[0](); // 0
funcs[1](); // 1
funcs[4](); // 4
&#13;