迭代循环中函数的参数

时间:2016-09-01 10:22:27

标签: javascript

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

3 个答案:

答案 0 :(得分:1)

Mikelis Baltruks所述,您必须使用.bind

您可以使用

goto.bind(null, i+1)

仅将索引映射到它。如果您也想获得按钮,可以使用

goto.bind(btn, i+1)

Sample JSFiddle

绑定

.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);
}

正如其他人所示,这可以通过多种方式完成。但这应该解释为什么它正在发生。请问任何问题。