我在我的JavaScript文件上使用了JSLint。它抛出错误:
for( ind in evtListeners ) {
第41行字符9的问题:for in的主体应该是 包装在if语句中以过滤不需要的 原型中的属性。
这是什么意思?
我在我的JavaScript文件上使用了JSLint。它抛出错误:
for( ind in evtListeners ) {
第41行字符9的问题:for in的主体应该是 包装在if语句中以过滤不需要的 原型中的属性。
这是什么意思?
首先,永远不要使用for in循环来枚举数组。从来没有。使用good old for(var i = 0;我< arr.length;我+ +)。
这背后的原因如下:JavaScript中的每个对象都有一个称为prototype的特殊字段。您添加到该字段的所有内容都将在该类型的每个对象上可访问。假设您希望所有数组都有一个很酷的名为filter_0的新函数,该函数将过滤掉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]
这是扩展对象和添加新方法的标准方法。很多库都这样做。 不过,现在让我们看看for in是如何工作的:
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
你明白了吗?它突然认为filter_0是另一个数组索引。当然,它并不是真正的数字索引,而是用于枚举对象字段,而不仅仅是数字索引。所以我们现在枚举每个数字索引和filter_0。但filter_0不是任何特定数组对象的字段,现在每个数组对象都有这个属性。
幸运的是,所有对象都有一个hasOwnProperty方法,该方法检查该字段是否真的属于对象本身,或者它是否只是从原型链继承而来,因此属于该类型的所有对象。
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
请注意,尽管这段代码对数组可以正常工作,但永远不要使用for in和for each in for数组。请记住,for 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 Statement A for class of statements should have the following form: for (initialization; condition; update) { statements } for (variable in object) { if (filter) { statements } } The first form should be used with arrays and with loops of a predeterminable number of iterations. The second form should be used with objects. Be aware that members that are added to the prototype of the object will be included in the enumeration. It is wise to program defensively by using the hasOwnProperty method to distinguish the true members of the object: for (variable in object) { if (object.hasOwnProperty(variable)) { statements } }
Crockford还制作了一个关于YUI剧院的系列视频,在视频中他谈到了这一点。如果你对javascript有点兴趣,一定要看Crockford关于javascript的系列视频/演讲。
瓦瓦的回答很中肯。如果使用jQuery,则使用$.each()函数处理这个问题,因此使用它更安全。
$.each(evtListeners, function(index, elem) {
// your code
});
当然,这样说有点极端
...永远不要使用for in循环to 枚举数组。从来没有。使用 (var I = 0; 我< arr.length;我+ +)
?
道格拉斯·克罗克福德节选中的这部分值得强调
…第二种形式应该用with 对象……
如果你需要一个关联数组(又名哈希表/字典),其中键是命名的,而不是数字索引,你将不得不实现它作为一个对象,例如var myAssocArray = {key1: "value1", key2: "value2"…};
In this case myAssocArray.length will come up null (because this object doesn't have a 'length' property), and your i < myAssocArray.length won't get you very far. In addition to providing greater convenience, I would expect associative arrays to offer performance advantages in many situations, as the array keys can be useful properties (i.e. an array member's ID property or name), meaning you don't have to iterate through a lengthy array repeatedly evaluating if statements to find the array entry you're after.
无论如何,也感谢JSLint错误消息的解释,我将使用'isOwnProperty'检查现在通过我的无数关联数组交互!
@all——JavaScript中的所有东西都是一个对象(),所以像“只在对象上使用这个”这样的语句有点误导人。此外,JavaScript不是强类型的,所以1 == "1"是真的(尽管1 === "1"不是真的,Crockford在这方面做得很好)。当涉及到JS中数组的编程概念时,类型在定义中很重要。
@Brenton -没有必要成为术语独裁者;“关联数组”,“字典”,“哈希”,“对象”,这些编程概念都适用于JS中的一个结构。它是name (key, index)值对,其中值可以是任何其他对象(字符串也是对象)
所以, new Array()与[]相同
new Object()大致类似于{}
var myarray = [];
创建一个数组结构,其中所有索引(即键)必须为整数。它还允许通过.push()自动分配新索引
var myarray = ["one","two","three"];
确实最好通过(初始化;条件;更新){处理
但是:
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在:http://jsperf.com/each-vs-for-in/2
不同的浏览器/版本处理它的方式不同,但似乎$。每一种都是性能上最便宜的选择。
如果你使用for in来遍历一个关联数组/对象,知道你在寻找什么,忽略其他一切,使用$。每一个如果你使用jQuery,或者只是在(然后休息;一旦你到达了你所知道的最后一个元素)
如果你在一个数组中迭代每个键对来执行一些事情,如果你不使用jQuery,应该使用hasOwnProperty方法,并使用$。每一个如果你使用jQuery。
如果你不需要关联数组,请使用for(i=0;i<o.length;i++)。哈哈,chrome比for in或$.each快97%
坏的:(jsHint将抛出错误)
for (var name in item) {
console.log(item[name]);
}
好:
for (var name in item) {
if (item.hasOwnProperty(name)) {
console.log(item[name]);
}
}
老实说,添加一整行只是为了检查键是否存在,而使用应该迭代对象的键的语法会导致..无用的。只需使用Object.keys(obj)即可。替换为forEach(key => {})