【问题标题】:Javascript: Binding a custom object method to an event listenerJavascript:将自定义对象方法绑定到事件侦听器
【发布时间】:2016-04-06 20:25:04
【问题描述】:

我卡在 Javascript 的事件处理程序方面。

rowCells[j] 是对唯一对象的引用。 galleryCell 也是对新创建对象的引用。按理说两者可以联系在一起。

但是,这两个引用似乎根本没有绑定在一起以使事件侦听器正常工作。所有单元格都被分配给相同的东西(最后一个 galleryCell 对象)。

galleryCell 变量在一个 for 循环中,在每次迭代时都会获得一个新的引用。为什么这些引用会丢失?

function TypeGallery (galleryObj)
{  //receives the <div> element that contains rows and cells of a gallery

   //Properties --------------
   var galleryCellArr = [];   //array of galleryZoomCell objects

   //Methods -----------------  
   var Initialize  = function ()
   {
      var rows     = galleryObj.children;
      var rowCount = rows.length;
      for (var i=0;i<rowCount;i++)
      {
         var rowCells     = rows[i].children;
         var rowCellCount = rowCells.length;
         for (var j=0;j<rowCellCount;j++)
         {
            var sliderObj   = new TypeSlider(300,1,false);
            var galleryCell = new TypeGalleryZoomCell(rowCells[j],sliderObj)
            galleryCellArr.push(galleryCell);

            rowCells[j].onmousedown = function () {galleryCell.Deploy();};
            rowCells[j].onmouseup   = function () {galleryCell.Retract();};
         }
      }
   }

   //Initialization
   Initialize();
}

【问题讨论】:

  • galleryCell 变量的作用域不是 for 块,而是整个 Initialize 函数。因此,每次迭代都会完全重写它,因此当事件触发时,调用的函数只是 galleryCell 的最新分配。看看stackoverflow.com/questions/750486/…

标签: javascript


【解决方案1】:

尝试像这样在 for 循环中放置一个 javascript 闭包:

function TypeGallery (galleryObj)
{  //receives the <div> element that contains rows and cells of a gallery

   //Properties --------------
   var galleryCellArr = [];   //array of galleryZoomCell objects

   //Methods -----------------  
   var Initialize  = function ()
   {
      var rows     = galleryObj.children;
      var rowCount = rows.length;
      for (var i=0;i<rowCount;i++)
      {
         var rowCells     = rows[i].children;
         var rowCellCount = rowCells.length;
         for (var j=0;j<rowCellCount;j++)
         {
            (function(j) {

                var sliderObj   = new TypeSlider(300,1,false);
                var galleryCell = new TypeGalleryZoomCell(rowCells[j],sliderObj)
                galleryCellArr.push(galleryCell);

                rowCells[j].onmousedown = function () {galleryCell.Deploy();};
                rowCells[j].onmouseup   = function () {galleryCell.Retract();};

            })(j);
         }
      }
   }

   //Initialization
   Initialize();
}

【讨论】:

  • 是的,但请注意,最好在循环外创建一个函数,然后在循环内调用它,而不是在每次迭代时创建一个新的匿名函数
  • 哇,是的,这行得通。谢谢你的回答!现在我需要回过头来弄清楚为什么我对 Javascript 作用域的理解存在这个盲点。
【解决方案2】:

好的,我现在了解 Javascript 和块范围限制的问题。

在此过程中,我发现了第二个可能的解决方法:
将 for 循环中的 'var' 替换为 'let' 是否有任何异议或警告?
据我所知,这段代码运行良好。有什么隐患吗?

   var Initialize  = function ()
   {
      var rowsArr  = galleryObj.children;
      var rowCount = rowsArr.length;
      for (let i=0;i<rowCount;i++)
      {  //Javascript does not understand block-scope unless the let keyword
         let rowCellsArr  = rowsArr[i].children;
         let rowCellCount = rowCellsArr.length;
         for (let j=0;j<rowCellCount;j++) 
         {
            //Attach (rowCellsArr[j]);

            let sliderObj   = new TypeSlider(300,1,false);
            let galleryCell = new TypeGalleryZoomCell(rowCellsArr[j],sliderObj);
            galleryCellArr.push(galleryCell); 

            galleryCellArr[galleryCellArr.length-1].cell.onmousedown = function () {galleryCell.Deploy();};
            galleryCellArr[galleryCellArr.length-1].cell.onmouseup   = function () {galleryCell.Retract();};

         }
      }
   }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2012-02-06
    • 2011-12-09
    • 2021-09-28
    • 1970-01-01
    相关资源
    最近更新 更多