如何重构此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塞进你的喉咙,但这似乎是一种对你非常有用的情况,比如:
您可以通过向每个链接添加类“trackable”来启用跟踪,并使用eg$(this).attr('rel')将链接映射到查找表$('a.trackable').click(function(e) { clicky.log(url, name, 'outbound'); };
希望有意义。您可以创建一个函数来构建事件处理程序,例如: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 }
委派是一种更好的方法。JSLint抱怨是因为每次在循环中都要创建一个新函数。但是,与其在文档上设置单个事件来侦听所有单击事件,不如在所有分配了id的根元素上设置一个处理程序。可以对所有这些元素重用单个处理程序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
向每个根元素注册上述处理程序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。很高兴你觉得它有用。干杯