我生成通过JavaScript(使用jQuery)的无序列表。 每个列表项必须接受自己的事件侦听器“click'事件。 不过,我遇到了麻烦连接到合适的项目的权利回调。 A(剥离)的代码示例可能被清除了一点东西:
for(class_id in classes) {
callback = function() { this.selectClass(class_id) };
li_item = jQuery('<li></li>')
.click(callback);
}
事实上,更多的是在本次迭代中事,但我不认为这是问题密切相关。 在任何情况下,发生了什么是回调函数似乎被引用 ,而不是存储 (复制)。 最终结果? 当用户点击任何列表项的,它总是会执行动作的最后 class_id
中classes
阵列,因为它使用存储在功能callback
在说具体点。
我发现肮脏的解决方法(如解析href
在一个封闭的属性a
元素),但我不知道是否有一种方式来实现自己的目标在“干净”的方式。 如果我的做法是令人震惊的,请告诉我,只要你告诉我,为什么:-)谢谢!
Answer 1:
这是做你想要什么更好的更清洁的方式。
添加信息类标识码到使用元素。数据()。
然后使用.live()如何将点击处理程序添加到所有的新元素,这避免了X *点击功能。
for(class_id in classes) {
li_item = jQuery('<li></li>').data('class_id', class_id).addClass('someClass');
}
//setup click handler on new li's
$('li.someClass').live('click', myFunction )
function myFunction(){
//get class_id
var classId = $(this).data('class_id');
//do something
}
Answer 2:
这是一个经典的“你需要一个封闭”的问题。 下面是通常发挥出来。
- 遍历一些值
- 定义/在使用迭代变量迭代指定功能
- 您了解,每一个函数从最后一次迭代只使用值。
- WTF?
同样,当你看到这种模式,就应该立即让你觉得“关闭”
扩展你的例子,这里是你如何把一个封闭
for ( class_id in classes )
{
callback = function( cid )
{
return function()
{
$(this).selectClass( cid );
}
}( class_id );
li_item = jQuery('<li></li>').click(callback);
}
然而,jQuery中的这种特殊情况下,你不应该需要一个封闭-但我要问你的变量的性质classes
-是一个对象? 因为你遍历一个for-in循环,这表明目标。 而对于我来说,这引出了一个问题,你为什么不保存在这个数组? 因为如果你是,你的代码可能仅仅是这一点。
jQuery('<li></li>').click(function()
{
$(this).addClass( classes.join( ' ' ) );
});
Answer 3:
您的代码:
for(class_id in classes) {
callback = function() { this.selectClass(class_id) };
li_item = jQuery('<li></li>')
.click(callback);
}
这主要是好的,只有一个问题。 变量callback
是全球性的; 所以你的每一次循环,要覆盖它。 把var
关键字在它前面范围在本地,你应该罚款。
编辑点评:它可能不是全球正如你所说的,但它的for循环的范围之内。 因此,该变量是相同的参考每轮循环。 把var
在循环播放范围来循环,每次做一个新的参考。
Answer 4:
我的JavaScript富是相当薄弱的,但据我所知它在堆栈上受封参考局部变量(和堆栈帧使用该功能,再次,非常粗略传来传)。 你的榜样确实不起作用,因为每个功能保持同一个变量的引用。 尝试而不是创建,创建封闭,即不同的功能:
function createClosure(class_id) {
callback = function() { this.selectClass(class_id) };
return callback;
}
然后:
for(class_id in classes) {
callback = createClosure(class_id);
li_item = jQuery('<li></li>').click(callback);
}
这是一个有点当然是杂牌的,有可能是更好的方法。
Answer 5:
你为什么不能产生所有这些,然后调用类似
$(".li_class").click(function(){ this.whatever() };
编辑:
如果您需要添加更多的类,只是与所有的类名的循环创建一个字符串,并使用它作为你的选择。
$(".li_class1, .li_class2, etc").click(function(){ this.whatever() };
Answer 6:
或者你也可以在附加类标识码这些列表项的.data()。
$("<li />").data("class_id", class_id).click(function(){
alert("This item has class_id "+$(this).data("class_id"));
});
要小心,虽然:你重新创建回调函数,每$("<li />")
调用。 我不知道关于JavaScript的执行细节,但是这可能是内存价格昂贵。 相反,你可以这样做
function listItemCallback(){
alert("This item has class_id "+$(this).data("class_id"));
}
$("<li />").data("class_id", class_id).click(listItemCallback);
文章来源: How to assign event callbacks iterating an array in javascript (jQuery)