JS Nooblord这里给出一些上下文我最近创建了我的第一个基于JQuery的图像滑块,我当前正试图在页面加载时动态生成控制按钮列表。
到目前为止,我已经成功创建了按钮,但是在编写onclick函数时,我遇到了在for循环中调用另一个函数(带参数)的问题。
我很难解释事情,但这里是代码;
function addControls(){
var x = document.getElementById('slider').childElementCount;
for (var i = 0; i < x; i++) {
var ul = document.getElementById('slider-control');
var li = document.createElement("li");
var btn = document.createElement("Button");
btn.onclick = function() {
goto(i);
};
btn.appendChild(document.createTextNode(i + 1));
ul.appendChild(li);
li.appendChild(btn);
}
}
function goto(index){
alert(index);
}
以下是JSFiddle预览。
我期望每个按钮调用goto函数及其在循环中的相应位置,但是每个生成的按钮都带有onclick函数,使用循环中的最后一个索引(4)。
我最初的想法是在循环完成后渲染按钮而不是在循环的每次迭代中?如果有人对我正在做的事情有任何提示和替代方案,我会非常感激。
谢谢,
-Dodd
答案 0 :(得分:1)
如Mikelis Baltruks所述,您必须使用.bind
。
您可以使用
goto.bind(null, i+1)
仅将索引映射到它。如果您也想获得按钮,可以使用
goto.bind(btn, i+1)
.bind
用于更改函数的上下文。它的语法是
functionName.bind(context, argumentList);
这将使用新绑定的上下文创建函数引用。
您还可以使用.apply
执行此任务。区别在于,apply expect参数为array,bind期望逗号分隔列表。
注意:此功能只会注册事件而不会调用它。
答案 1 :(得分:0)
你需要在循环中创建一个闭包,这应该有效:
var x = document.getElementById('slider').childElementCount;
for (var i = 0; i < x; i++) {
(function (i) {
var ul = document.getElementById('slider-control');
var li = document.createElement("li");
var btn = document.createElement("Button");
btn.onclick = function() {
goto(i);
};
btn.appendChild(document.createTextNode(i + 1));
ul.appendChild(li);
li.appendChild(btn);
})(i);
}
function goto(index) {
alert(index);
}
https://jsfiddle.net/g8qeq29e/6/
或使用ES6 let
关键字;
function addControls(){
var x = document.getElementById('slider').childElementCount;
for (let i = 0; i < x; i++) {//change var to let here
var ul = document.getElementById('slider-control');
var li = document.createElement("li");
var btn = document.createElement("Button");
btn.onclick = function() {
goto(i);
};
btn.appendChild(document.createTextNode(i + 1));
ul.appendChild(li);
li.appendChild(btn);
}
}
function goto(index){
alert(index);
}
答案 2 :(得分:0)
问题是对i
的引用。
for (var i = 0; i < x; i++) {
var btn = document.createElement("Button");
btn.onclick = function() {
goto(i);
// any variable reference will use the latest value
// so when `onclick` is actually run, the loop will have continued on to completion, with i == 4
};
}
每个onclick处理程序都需要一个单独的变量来引用。你可以通过创建一个闭包来做到这一点:
function makeOnclick(i) {
// `i` is now a completely separate "variable",
// so it will not be updated while the loop continues running
return function() { goto(i); };
}
for (var i = 0; i < x; i++) {
var btn = document.createElement("Button");
btn.onclick = makeOnclick(i);
}
正如其他人所示,这可以通过多种方式完成。但这应该解释为什么它正在发生。请问任何问题。