如何分配事件回调迭代在JavaScript数组(jQuery的)如何分配事件回调迭代在JavaScr

2019-05-12 05:48发布

我生成通过JavaScript(使用jQuery)的无序列表。 每个列表项必须接受自己的事件侦听器“click'事件。 不过,我遇到了麻烦连接到合适的项目的权利回调。 A(剥离)的代码示例可能被清除了一点东西:

for(class_id in classes) {
    callback = function() { this.selectClass(class_id) };
    li_item = jQuery('<li></li>')
                .click(callback);
}

事实上,更多的是在本次迭代中事,但我不认为这是问题密切相关。 在任何情况下,发生了什么是回调函数似乎被引用 ,而不是存储 (复制)。 最终结果? 当用户点击任何列表项的,它总是会执行动作的最后 class_idclasses阵列,因为它使用存储在功能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:

这是一个经典的“你需要一个封闭”的问题。 下面是通常发挥出来。

  1. 遍历一些值
  2. 定义/在使用迭代变量迭代指定功能
  3. 您了解,每一个函数从最后一次迭代只使用值。
  4. 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)