Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/88.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript “vars退货警报”;“长度”;或;项目「;_Javascript_Html_Dom_Lambda - Fatal编程技术网

Javascript “vars退货警报”;“长度”;或;项目「;

Javascript “vars退货警报”;“长度”;或;项目「;,javascript,html,dom,lambda,Javascript,Html,Dom,Lambda,我有一个16x16表,我向所有td分配了一个lambda函数(将参数传递给实际函数),如下所示: function handlerAsignment() { var trs = document.getElementsByTagName("tr"); var tds; for (tr in trs) { tds = trs[tr].getElementsByTagName("td"); for (td in tds){

我有一个16x16表,我向所有td分配了一个lambda函数(将参数传递给实际函数),如下所示:

function handlerAsignment()
{
    var trs = document.getElementsByTagName("tr");
    var tds;

    for (tr in trs) {
        tds = trs[tr].getElementsByTagName("td");

        for (td in tds){
            tds[td].onclick = function() {
                atack(tr, td);
            };
        }
    }
}
正如您将看到的,我必须传递关于正确tr的tr编号和td编号。 但我有这个功能:

function atack(tr, td)
{
   alert("Tr: " +tr+ " td: " +td);
}
function atack(evt) {
  var cell = this;
  var row = cell.parentNode; 

  alert("Tr: " + row + " td: " + cell);
}
这会显示消息“Tr:item td:length”为什么?


建议:我不想在函数atack中使用事件来检测正确的td。我需要这些参数来访问16x16多维数组(与表相同,但有更多信息)。

这是典型的闭包误解。您分配给
onclick
的函数(闭包)具有对
tr
td
变量的持久引用,而不是创建时的变量副本。因此,所有的
onclick
函数都使用相同的变量和值;两个循环结束时的值

这里通常的答案是使用生成器函数,以便它们使用单独的变量:

function handlerAsignment()
{
    var trs = document.getElementsByTagName("tr");
    var tds;

    for (tr in trs) {
        tds = trs[tr].getElementsByTagName("td");

        for (td in tds){
            tds[td].onclick = buildHandler(tr, td);
        }
    }
}

function buildHandler(tr, td) {
    return function() {
        atack(tr, td);
    };
}
现在,处理程序关闭传递到
buildHandler
tr
td
参数,而不是循环中使用的
tr
td
变量。因为这些参数永远不会改变(每个对
buildHandler
的调用都有自己的参数),所以它解决了这个问题

更多关于我的博客:


还有两件事值得一提:

  • 您没有在任何地方声明
    td
    tr
    ,因此您正沦为

  • 您不需要使用
    for in
    来循环
    节点列表
    实例
    for in
    循环遍历对象的属性名称。将它与主机提供的对象(如
    NodeList
    )一起使用不能保证工作,而且依赖于主机提供的对象使某些内容可枚举,而其他内容不可枚举。改用标准循环。因此:

    function handlerAsignment()
    {
      var trs = document.getElementsByTagName("tr");
      var tds;
      var trIndex, tdIndex;
    
      for (trIndex = 0; trIndex < trs.length; ++trIndex) {
        tds = trs[trIndex].getElementsByTagName("td");
    
        for (tdIndex = 0; tdIndex < tds.length; ++tdIndex){
          tds[tdIndex].onclick = buildHandler(trIndex, tdIndex);
        }
      }
    }
    
    function buildHandler(tr, td) {
      return function() {
        atack(tr, td);
      };
    } 
    
    |


    您可以在任何类似数组的对象上安全地使用
    Array#forEach
    ,而不仅仅是数组<代码>节点列表对象类似于数组。

    这是经典的闭包误解。您分配给
    onclick
    的函数(闭包)具有对
    tr
    td
    变量的持久引用,而不是创建时的变量副本。因此,所有的
    onclick
    函数都使用相同的变量和值;两个循环结束时的值

    这里通常的答案是使用生成器函数,以便它们使用单独的变量:

    function handlerAsignment()
    {
        var trs = document.getElementsByTagName("tr");
        var tds;
    
        for (tr in trs) {
            tds = trs[tr].getElementsByTagName("td");
    
            for (td in tds){
                tds[td].onclick = buildHandler(tr, td);
            }
        }
    }
    
    function buildHandler(tr, td) {
        return function() {
            atack(tr, td);
        };
    }
    
    现在,处理程序关闭传递到
    buildHandler
    tr
    td
    参数,而不是循环中使用的
    tr
    td
    变量。因为这些参数永远不会改变(每个对
    buildHandler
    的调用都有自己的参数),所以它解决了这个问题

    更多关于我的博客:


    还有两件事值得一提:

  • 您没有在任何地方声明
    td
    tr
    ,因此您正沦为

  • 您不需要使用
    for in
    来循环
    节点列表
    实例
    for in
    循环遍历对象的属性名称。将它与主机提供的对象(如
    NodeList
    )一起使用不能保证工作,而且依赖于主机提供的对象使某些内容可枚举,而其他内容不可枚举。改用标准循环。因此:

    function handlerAsignment()
    {
      var trs = document.getElementsByTagName("tr");
      var tds;
      var trIndex, tdIndex;
    
      for (trIndex = 0; trIndex < trs.length; ++trIndex) {
        tds = trs[trIndex].getElementsByTagName("td");
    
        for (tdIndex = 0; tdIndex < tds.length; ++tdIndex){
          tds[tdIndex].onclick = buildHandler(trIndex, tdIndex);
        }
      }
    }
    
    function buildHandler(tr, td) {
      return function() {
        atack(tr, td);
      };
    } 
    
    |

    您可以在任何类似数组的对象上安全地使用
    Array#forEach
    ,而不仅仅是数组
    NodeList
    对象类似于数组。

    for(tr-in-trs)
    不是您想要的东西。它依次将
    tr
    设置为
    trs
    的每个属性的名称。由于
    trs
    是一个
    NodeList
    ,它的命名属性是
    length
    及其
    方法

    for(tr of trs)
    语法可以工作,但您是为浏览器编码的,浏览器对此的支持并不普遍

    NodeList
    不是一个真正的数组,因此您无法轻松地在其上使用
    array.forEach

    因此,您最好使用
    for(var i=0;i
    plus
    trs[i]
    plus T.J.
    buildHandler
    技巧来确保您的处理程序关闭的变量在创建关闭后不会更改。

    for(trs中的tr)
    不是您想要的东西。它依次将
    tr
    设置为
    trs
    的每个属性的名称。由于
    trs
    是一个
    NodeList
    ,它的命名属性是
    length
    及其
    方法

    for(tr of trs)
    语法可以工作,但您是为浏览器编码的,浏览器对此的支持并不普遍

    NodeList
    不是一个真正的数组,因此您无法轻松地在其上使用
    array.forEach


    因此,您最好使用
    for(var i=0;i
    plus
    trs[i]
    加上T.J.的
    buildHandler
    技巧,以确保您的处理程序关闭的变量在创建闭包后不会更改。

    房间里没有人讨论过大象:创建一个将引用传递给它所在元素的处理程序是不必要的,因为可以将处理程序设置为将该元素作为引用这是默认设置

    类似地,当该元素作为
    this.parentNode
    可用时,将引用传递给该元素的父元素也没有意义

    使用addEventListener或attachEvent(视情况而定)添加侦听器的简单函数:

      function addListener(element, event, fn) {
    
        // Use addEventListener if available
        if (element.addEventListener) {
          element.addEventListener(event, fn, false);
    
        // Otherwise use attachEvent, set this and event
        } else if (element.attachEvent) {
          element.attachEvent('on' + event, (function (el) {
            return function() {
              fn.call(el, window.event);
            };
          }(element)));
    
          // Break closure and primary circular reference to element
          element = null;
        }
      }
    
    使用上述方法将侦听器连接到单元格上,然后在atack(攻击?)功能中:

    function atack(tr, td)
    {
       alert("Tr: " +tr+ " td: " +td);
    }
    
    function atack(evt) {
      var cell = this;
      var row = cell.parentNode; 
    
      alert("Tr: " + row + " td: " + cell);
    }
    

    如果您调查事件委派,您可能会发现您只需要一个侦听器就可以了。

    没有人在房间里讨论过大象:创建一个将引用传递给el的处理程序