编辑:我想通了。我只是走了一条完全不同的路线,制作了一个Button类,并在我的实际画布上使用矩形来表示它们。
我试图在p5js中以编程方式使多个可单击按钮,但我陷入了一个问题。所有的div都将被创建,显示并具有正确的HTML关联,但是无论单击哪个,都仅会诱导最后一个按钮的功能。
这是一张照片:
这些是我右边的按钮,但是无论您单击何处,选择的颜色始终是底部的紫色。
这是我的代码:
for (var i = 0; i < colorCodes.length ; i++){
var div = createDiv(str(i));
div.parent('control-holder');
div.style('background-color', colorCodes[i]);
div.style('height', '40px');
div.mousePressed(function(){
console.log(div.html()); //always prints 7
changeColor(int(div.html()));
});
buttons.push(div);
}
非常感谢您的帮助,我不明白为什么它不起作用。
答案 0 :(得分:1)
这是一个常见的JavaScript陷阱。
使用var
关键字时,您创建的变量具有功能范围,这意味着变量(在您的情况下为i
变量)保持其值直到函数结束,直到循环结束。考虑以下代码:
for(var i = 0; i < 10; i++){
console.log('i: ' + i);
}
console.log('final i: ' + i);
此代码将在循环中打印出0-9,然后在循环退出后打印出10。
现在,让我们稍微更改一下代码:
for(var i = 0; i < 10; i++){
setTimeout(function(){
console.log('i: ' + i);
}, 1000);
}
console.log('final i: ' + i);
现在,循环将设置超时回调。此代码将首先打印出final i: 10
,然后将打印出i: 10
10次。这是因为在{strong>之前调用回调函数之前发生了console.log('final i: ' + i);
行。并且由于该变量具有函数作用域,因此它将使用它给出的最后一个值。这是另一个示例:
var i = 42;
setTimeout(function() {
console.log('i: ' + i);
}, 1000);
i = 37;
您可能希望此代码能打印出42
,但同样,此代码运行后,在 之后会调用回调函数,因此在被调用时i
是37
。
无论如何,回到您的代码。希望上面的示例向您展示代码中的情况:var
关键字创建了一个函数范围的变量,这意味着在调用mousePressed回调时,该变量将保留其最后一个设置值。 / p>
传统上,解决此问题的方法是通过另一个函数调用:
for (var i = 0; i < 10; i++) {
callSetTimeout(i);
}
console.log('final i: ' + i);
function callSetTimeout(i) {
setTimeout(function() {
console.log('i: ' + i);
}, 1000);
}
但是从JavaScript 6开始,您可以使用let
关键字代替var
:
for(let i = 0; i < 10; i++){
setTimeout(function(){
console.log('i: ' + i);
}, 1000);
}
这将为您的变量提供 block作用域,这意味着该变量仅在for
循环范围内。结果,循环的每次迭代都会得到自己的副本,您的函数现在将按预期的方式工作。