在循环中迭代函数的形参
Iterating parameters for a function within a loop
JS noblord在这里,给一些背景,我最近创建了我的第一个基于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)的最后一个索引。
我最初的想法是按钮在循环完成后呈现,而不是在循环的每次迭代中?如果有人对我正在做的事情有任何建议和替代方案,我将不胜感激。
谢谢,
多德
正如Mikelis Baltruks评论的那样,您将不得不使用.bind
。
可以使用
goto.bind(null, i+1)
只映射索引到它。如果希望也获得按钮,可以使用
goto.bind(btn, i+1)
样本JSFiddle 绑定 .bind
用于改变函数的上下文。其语法是
functionName.bind(context, argumentList);
这将创建一个带有新绑定上下文的函数引用。
也可以使用.apply
。不同之处在于,apply期望参数为数组,而bind期望参数为逗号分隔的列表。
注意:这个函数只会注册事件而不会调用它。
参考- .bind
- 苹果
- 调用(),apply() vs bind()
问题是对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);
}
这可以通过多种方式实现,正如其他人所展示的那样。但这应该可以解释为什么会发生。
你需要在循环中创建一个闭包,这应该可以工作:
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);
}
相关文章:
- 在回调函数中使用参数值
- 如何获取函数参数值
- 高位图堆积柱形图更改图例ItemClick函数
- 如何使用 javascript 函数设置 href 参数值
- 如何使 JavaScript 变量等于函数参数值
- 微信/微信JavaScript桥(WeixinJSBridge)使用微信JSBridgeReady事件监听器并函数作为参
- Jquery函数无法使用参数值
- 没有参数的jQuery outerHeight()函数返回对象而不是参数值
- 如何使用bookmarklet从HTML页面获取函数参数值
- 函数调用作为参数值
- 使用实参调用Javascript函数,并将实参用作变量名
- 将函数形参值传递给该函数内部的函数
- 什么是toString形参
- 这个函数如何将实参传递给另一个内部函数形参
- 在coffeescript中定义函数(或方法)时,使用":"有什么区别?和“=”;分隔函数名和参数列
- 不能理解为什么这个函数返回false如果我改变参数值
- 为什么我的回调函数接收未定义的参数值
- 如何在coffeescript中向安全闭包添加实参/形参
- 将字符串传递给函数与带默认形参调用函数的区别
- 在循环中迭代函数的形参