我在我的JavaScript文件上使用了JSLint。它抛出错误:
for( ind in evtListeners ) {
第41行第9个字符的问题:for in的正文应该是 包装在if语句中以过滤不需要的
这是什么意思?
这意味着你应该用hasOwnProperty方法来过滤evtlistener的属性。
首先,从来没有使用for in循环枚举数组。从来没有。使用好的老for(var i = 0; i<arr.length; i++)。
for in
for(var i = 0; i<arr.length; i++)
这背后的原因如下:JavaScript中的每个对象都有一个名为prototype的特殊字段。您添加到该字段的所有内容都将在该类型的每个对象上可访问。假设你想让所有数组都有一个很酷的新函数filter_0来过滤掉0。
prototype
filter_0
Array.prototype.filter_0 = function() { var res = []; for (var i = 0; i < this.length; i++) { if (this[i] != 0) { res.push(this[i]); } } return res; }; console.log([0, 5, 0, 3, 0, 1, 0].filter_0()); //prints [5,3,1]
var listeners = ["a", "b", "c"]; for (o in listeners) { console.log(o); } //prints: // 0 // 1 // 2 // filter_0
你明白了吗?它突然认为filter_0是另一个数组索引。当然,它不是一个真正的数值索引,但for in枚举对象字段,而不仅仅是数值索引。所以我们现在正在枚举每个数字索引而且 filter_0。但是filter_0不是任何特定数组对象的字段,现在每个数组对象都有这个属性。
幸运的是,所有对象都有一个hasOwnProperty方法,该方法检查该字段是否真的属于对象本身,还是只是从原型链继承而来,因此属于该类型的所有对象。
hasOwnProperty
for (o in listeners) { if (listeners.hasOwnProperty(o)) { console.log(o); } } //prints: // 0 // 1 // 2
注意,虽然这段代码对数组的工作如预期的那样,但你绝不应该,从来没有,对数组使用for in和for each in。记住for in枚举对象的字段,而不是数组的索引或值。
for each in
var listeners = ["a", "b", "c"]; listeners.happy = "Happy debugging"; for (o in listeners) { if (listeners.hasOwnProperty(o)) { console.log(o); } } //prints: // 0 // 1 // 2 // happy
jslint的作者Douglas Crockford就这个问题写过(也说过)很多次。在他的网站的这页面上有一个部分涵盖了这一点:
for语句 A类语句应该有 以下形式: for (initialization; condition; update) { statements } for (variable in object) { if (filter) { statements } } 第一种形式应该用with 数组和a的循环 第二种形式应该用with 对象。要意识到成员 添加到原型的 对象将包含在 枚举。编程是明智的 防御上使用 方法进行区分 对象的真成员: for (variable in object) { if (object.hasOwnProperty(variable)) { statements } }
for语句
A类语句应该有 以下形式:
for (initialization; condition; update) { statements } for (variable in object) { if (filter) { statements } }
for (variable in object) { if (object.hasOwnProperty(variable)) { statements } }
Crockford还制作了一个关于YUI剧院的系列视频,在视频中他谈到了这一点。如果你对javascript有点兴趣,一定要看Crockford关于javascript的系列视频/演讲。
瓦瓦的回答很中肯。如果你使用jQuery,那么$.each()函数会处理这个问题,因此使用它更安全。
$.each()
$.each(evtListeners, function(index, elem) { // your code });
当然,这样说有点极端
< p >…永远不要使用for in循环to 枚举数组。从来没有。使用 (var I = 0; i< arr.length;我+ +)< / p >
?
道格拉斯·克罗克福德节选中的这部分值得强调
< p >…第二种形式应该用with 对象…< / p >
如果你需要一个关联数组(又名哈希表/字典),其中键是命名的,而不是数字索引,你将不得不将其实现为一个对象,例如var myAssocArray = {key1: "value1", key2: "value2"...};。
var myAssocArray = {key1: "value1", key2: "value2"...};
在这种情况下,myAssocArray.length将返回null(因为这个对象没有'length'属性),而你的i < myAssocArray.length不会让你走得太远。除了提供更大的便利性之外,我还希望关联数组在许多情况下提供性能优势,因为数组键可以是有用的属性(即数组成员的ID属性或名称),这意味着您不必重复遍历一个冗长的数组来计算if语句以找到您要查找的数组项。
myAssocArray.length
i < myAssocArray.length
无论如何,也感谢JSLint错误消息的解释,我将使用'isOwnProperty'检查现在通过我的无数关联数组交互!
@all——JavaScript中的所有东西都是一个对象(),所以像“只在对象上使用这个”这样的语句有点误导人。此外,JavaScript不是强类型的,所以1 == "1"是真的(尽管1 === "1"不是真的,Crockford在这方面做得很好)。当涉及到JS中数组的编程概念时,类型在定义中很重要。
@Brenton -没有必要成为术语独裁者;“关联数组”,“字典”,“哈希”,“对象”,这些编程概念都适用于JS中的一个结构。它是name (key, index)值对,其中值可以是任何其他对象(字符串也是对象)
new Array()
[]
new Object()大致类似于{}
new Object()
{}
var myarray = [];
创建一个数组结构,其中所有索引(即键)必须为整数。它还允许通过.push()自动分配新索引
var myarray = ["one","two","three"];
的确是通过for(initialization;condition;update){最好的处理
for(initialization;condition;update){
但是:
var myarray = []; myarray[100] = "foo"; myarray.push("bar");
试试这个:
var myarray = [], i; myarray[100] = "foo"; myarray.push("bar"); myarray[150] = "baz"; myarray.push("qux"); alert(myarray.length); for(i in myarray){ if(myarray.hasOwnProperty(i)){ alert(i+" : "+myarray[i]); } }
也许不是数组的最佳用法,但只是说明事情并不总是明确的。
如果你知道键值,而且肯定不是整数,你唯一的数组类结构选项就是对象。
var i, myarray= { "first":"john", "last":"doe", 100:"foo", 150:"baz" }; for(i in myarray){ if(myarray.hasOwnProperty(i)){ alert(i+" : "+myarray[i]); } }
只是添加到for in/for/$的主题。每一个,我添加了一个jsperf测试用例使用$。每个vs for in: http://jsperf.com/each-vs-for-in/2
不同的浏览器/版本处理它的方式不同,但似乎$。每一种都是性能上最便宜的选择。
如果你使用for in来遍历一个关联数组/对象,知道你在寻找什么,忽略其他一切,使用$。每一个如果你使用jQuery,或者只是在(然后休息;一旦你到达了你所知道的最后一个元素)
如果你在一个数组中迭代每个键对来执行一些事情,如果你不使用jQuery,应该使用hasOwnProperty方法,并使用$。每一个如果你使用jQuery。
如果你不需要关联数组,总是使用for(i=0;i<o.length;i++)…lol chrome比for in或$.each快97%
for(i=0;i<o.length;i++)
$.each
坏的:(jsHint将抛出错误)
for (var name in item) { console.log(item[name]); }
好:
for (var name in item) { if (item.hasOwnProperty(name)) { console.log(item[name]); } }
诚实地说,添加一整行只是为了检查键是否存在,而使用的语法应该是遍历对象的键,这使得for .. in无用。只需使用Object.keys(obj).forEach(key => {}即可。
for .. in
Object.keys(obj).forEach(key => {}