如何重构此JavaScript代码以避免在循环中生成函数?

如何重构此JavaScript代码以避免在循环中生成函数?,javascript,function,loops,closures,event-delegation,Javascript,Function,Loops,Closures,Event Delegation,我为正在进行的项目编写了以下代码: var clicky_tracking = [ ['related-searches', 'Related Searches'], ['related-stories', 'Related Stories'], ['more-videos', 'More Videos'], ['web-headlines', 'Publication'] ]; for (var x = 0, length_x = clicky_tracking.length

我为正在进行的项目编写了以下代码:

var clicky_tracking = [
  ['related-searches', 'Related Searches'],
  ['related-stories', 'Related Stories'],
  ['more-videos', 'More Videos'],
  ['web-headlines', 'Publication']
];

for (var x = 0, length_x = clicky_tracking.length; x < length_x; x++) {
  links = document.getElementById(clicky_tracking[x][0])
                  .getElementsByTagName('a');
  for (var y = 0, length_y = links.length; y < length_y; y++) {
    links[y].onclick = (function(name, url) {
      return function() {
        clicky.log(url, name, 'outbound');
      };
    }(clicky_tracking[x][1], links[y].href));
  }
}
var clicky\u跟踪=[
[“相关搜索”,“相关搜索”],
[“相关故事”,“相关故事”],
[“更多视频”,“更多视频”],
[“网络标题”,“出版物”]
];
对于(变量x=0,长度x=clicky\u tracking.length;x
我想做的是:

  • 定义一个二维数组,每个实例的内部数组包含两个元素:一个
    id
    属性值(如“相关搜索”)和一个相应的描述(如“相关搜索”)
  • 对于每个内部数组,在
    文档中找到具有相应
    id
    属性的元素,然后收集所有

    因此,我的问题是:

    • 如何重构这段代码,使JSLint变得令人满意?或者,更好的是,有没有一种最佳实践方法可以做到这一点,而不管JSLint怎么想,我都没有找到
    • 我应该依靠活动授权吗?也就是说,将
      onclick
      事件处理程序附加到我的数组中具有
      id
      属性的
      文档
      元素,然后查看
      event.target
      ?我以前做过一次,并且理解了这个理论,但是我对细节非常模糊,我希望能得到一些关于这个问题的指导——假设这是一个可行的方法

    非常感谢您的帮助

    这段代码不太容易维护!我讨厌把jQuery塞进你的喉咙,但这似乎是一种对你非常有用的情况,比如:

    $('a.trackable').click(function(e) {
    
      clicky.log(url, name, 'outbound');
    };
    
    您可以通过向每个链接添加类“trackable”来启用跟踪,并使用eg$(this).attr('rel')将链接映射到查找表


    希望有意义。

    您可以创建一个函数来构建事件处理程序,例如:

    function createClickHandler(url, name) {
      return function () {
        clicky.log(url, name, 'outbound');
      };
    }
    
    for (var x = 0, length_x = clicky_tracking.length; x < length_x; x++) {
      links = document.getElementById(clicky_tracking[x][0]) // NOTE:links should be 
                      .getElementsByTagName('a');            // declared at the top
      for (var y = 0, length_y = links.length; y < length_y; y++) {
        links[y].onclick = createClickHandler(clicky_tracking[x][1], links[y].href);
      }
    }
    
    函数createClickHandler(url、名称){
    返回函数(){
    log(url、名称、“出站”);
    };
    }
    对于(变量x=0,长度x=clicky\u tracking.length;x
    我还认为这也是一个非常好的选择,您可以非常轻松地实施它:

    var clicky_tracking = [
      ['related-searches', 'Related Searches']
      //...
    ], elem;
    
    function createClickHandler(name) { // capture only the 'name' variable
      return function (e) {
        e = e || window.event; // cross-browser way to get the event object
        var target = e.target || e.srcElement; // and the event target
    
        if (target.nodeName == "A") { // make sure that the target is an anchor
          clicky.log(target.href, name, 'outbound');
        }
      };
    }
    
    for (var x = 0, len = clicky_tracking.length; x < len; x++) {
      elem = document.getElementById(clicky_tracking[x][0]); // find parent element
      elem.onclick = createClickHandler(clicky_tracking[x][1]); // bind the event
    }
    ​
    
    var clicky\u跟踪=[
    [“相关搜索”,“相关搜索”]
    //...
    ],elem;
    函数createClickHandler(name){//仅捕获'name'变量
    返回函数(e){
    e=e | | window.event;//获取事件对象的跨浏览器方式
    var target=e.target | | e.srcmelement;//和事件目标
    如果(target.nodeName==“A”){//请确保目标是锚定
    clicky.log(target.href,名称“outbound”);
    }
    };
    }
    对于(变量x=0,len=clicky_tracking.length;x
    委派是一种更好的方法。JSLint抱怨是因为每次在循环中都要创建一个新函数。但是,与其在文档上设置单个事件来侦听所有单击事件,不如在所有分配了id的根元素上设置一个处理程序。可以对所有这些元素重用单个处理程序

    function logClick(event) {
        event = event || window.event;
        var link = event.target || event.srcElement;
    
        if(link.nodeName.toLowerCase() !== "a") {
            return;
        }
    
        var name = clicky_tracking[this.id];
        clicky.log(link.href, name, 'outbound');
    }
    
    向每个根元素注册上述处理程序

    for(var id in clicky_tracking) {
        var root = document.getElementById(id);
        root.onclick = logClick;
    }
    
    另外,为了避免在数组中搜索,我将
    clicky_tracking
    从数组更改为一个对象,以便更轻松地进行键控访问

    var clicky_tracking = {
      'related-searches': 'Related Searches',
      'related-stories': 'Related Stories',
      'more-videos': 'More Videos',
      'web-headlines': 'Publication'
    };
    

    谢谢你,詹姆斯!这是有道理的,我很欣赏你的回答和方法。不幸的是,我绝对不能在这个项目上使用jQuery,因为它部署在一个流量非常高的环境中,即使是24KB的jQuery也太多了?所以你真的会因为js的减少而减少你的对外流量?只是想一想:非常感谢,CMS!我希望我能接受你和阿努拉格的答案,但他们都很好,他的答案在几分钟内就第一个。FWIW,这对我很有帮助。谢谢你,阿努拉格!我真的很感激。这看起来很棒。谢谢@Bungle。很高兴你觉得它有用。干杯