Javascript JSLint 错误“for in 的主体应该包含在 if 语句中”是什么意思?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1963102/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does the JSLint error 'body of a for in should be wrapped in an if statement' mean?
提问by jrharshath
I used JSLinton a JavaScript file of mine. It threw the error:
我在我的 JavaScript 文件中使用了JSLint。它抛出了错误:
for( ind in evtListeners ) {
Problem at line 41 character 9: The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.
第 41 行字符 9 的问题:for in 的主体应该包含在 if 语句中,以从原型中过滤掉不需要的属性。
What does this mean?
这是什么意思?
回答by vava
First of all, neveruse a for inloop to enumerate over an array. Never. Use good old for(var i = 0; i<arr.length; i++).
首先,永远不要使用for in循环来枚举数组。绝不。用好旧for(var i = 0; i<arr.length; i++)。
The reason behind this is the following: each object in JavaScript has a special field called prototype. Everything you add to that field is going to be accessible on every object of that type. Suppose you want all arrays to have a cool new function called filter_0that will filter zeroes out.
这背后的原因如下:JavaScript 中的每个对象都有一个名为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]
This is a standard way to extend objects and add new methods. Lots of libraries do this.
However, let's look at how for inworks now:
这是扩展对象和添加新方法的标准方法。许多图书馆都这样做。但是,让我们看看for in现在是如何工作的:
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
Do you see? It suddenly thinks filter_0 is another array index. Of course, it is not really a numeric index, but for inenumerates through object fields, not just numeric indexes. So we're now enumerating through every numeric index andfilter_0. But filter_0is not a field of any particular array object, every array object has this property now.
你有看到?它突然认为 filter_0 是另一个数组索引。当然,它并不是真正的数字索引,而是for in通过对象字段进行枚举,而不仅仅是数字索引。所以我们现在正在枚举每个数字索引和filter_0. 但filter_0不是任何特定数组对象的字段,现在每个数组对象都具有此属性。
Luckily, all objects have a hasOwnPropertymethod, which checks if this field really belongs to the object itself or if it is simply inherited from the prototype chain and thus belongs to all the objects of that type.
幸运的是,所有对象都有一个hasOwnProperty方法,它检查这个字段是否真的属于对象本身,或者它是否只是从原型链继承,因此属于该类型的所有对象。
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
Note, that although this code works as expected for arrays, you should never, never, use for inand for each infor arrays. Remember that for inenumerates the fields of an object, not array indexes or values.
请注意,尽管此代码对数组按预期工作,但您不应该,从不,使用for in和for each in用于数组。请记住,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
回答by Breton
Douglas Crockford, the author of jslint has written (and spoken) about this issue many times. There's a section on thispage of his website which covers this:
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 } }
声明
A for 语句类应具有以下形式:
for (initialization; condition; update) { statements } for (variable in object) { if (filter) { statements } }第一种形式应与数组和可预定迭代次数的循环一起使用。
第二种形式应该与对象一起使用。请注意,添加到对象原型的成员将包含在枚举中。通过使用 hasOwnProperty 方法来区分对象的真实成员来防御性编程是明智的:
for (variable in object) { if (object.hasOwnProperty(variable)) { statements } }
Crockford also has a video series on YUI theater where he talks about this. Crockford's series of videos/talks about javascript are a must see if you're even slightly serious about javascript.
Crockford 在 YUI 剧院也有一个视频系列,他在那里谈到了这一点。Crockford 的关于 javascript 的系列视频/演讲是必须要看的,如果您对 javascript 有点认真的话。
回答by Taro Alan
Bad: (jsHint will throw a error)
不好:(jsHint 会抛出错误)
for (var name in item) {
console.log(item[name]);
}
Good:
好的:
for (var name in item) {
if (item.hasOwnProperty(name)) {
console.log(item[name]);
}
}
回答by HRJ
Vava's answer is on the mark. If you use jQuery, then the $.each()function takes care of this, hence it is safer to use.
Vava 的回答很到位。如果您使用 jQuery,则该$.each()函数会处理此问题,因此使用起来更安全。
$.each(evtListeners, function(index, elem) {
// your code
});
回答by wade
@all - everything in JavaScript is an object (), so statements like "only use this on objects" are a bit misleading. In addition JavaScript is not strongly typed so that 1 == "1" is true (although 1 === "1" is not, Crockford is big on this). When it comes to the progromatic concept of arrays in JS, typing is important in the definition.
@all - JavaScript 中的一切都是对象 (),所以像“只在对象上使用 this”这样的语句有点误导。此外,JavaScript 不是强类型的,因此 1 == "1" 为真(尽管 1 === "1" 不是,但 Crockford 对此很重视)。当谈到 JS 中数组的编程概念时,类型在定义中很重要。
@Brenton - No need to be a terminology dictator; "associative array", "dictionary", "hash", "object", these programming concepts all apply to one structure in JS. It is name (key, index) value pairs, where the value can be any other object (strings are objects too)
@Brenton - 无需成为术语独裁者;“关联数组”、“字典”、“哈希”、“对象”,这些编程概念都适用于JS中的一种结构。它是名称(键,索引)值对,其中值可以是任何其他对象(字符串也是对象)
So,
new Array()is the same as []
所以,
new Array()是一样的[]
new Object()is roughly similar to {}
new Object()大致类似于 {}
var myarray = [];
Creates a structure that is an array with the restriction that all indexes (aka keys) must be a whole number. It also allows for auto assigning of new indexes via .push()
创建一个数组结构,限制所有索引(又名键)必须是整数。它还允许通过 .push() 自动分配新索引
var myarray = ["one","two","three"];
Is indeed best dealt with via for(initialization;condition;update){
确实最好通过处理 for(initialization;condition;update){
But what about:
但是关于:
var myarray = [];
myarray[100] = "foo";
myarray.push("bar");
Try this:
尝试这个:
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]);
}
}
Perhaps not the best usage of an array, but just an illustration that things are not always clearcut.
也许不是数组的最佳用法,而只是说明事情并不总是一目了然。
If you know your keys, and definitely if they are not whole numbers, your only array like structure option is the object.
如果您知道您的键,并且如果它们不是整数,那么您唯一的类似数组的结构选项就是对象。
var i, myarray= {
"first":"john",
"last":"doe",
100:"foo",
150:"baz"
};
for(i in myarray){
if(myarray.hasOwnProperty(i)){
alert(i+" : "+myarray[i]);
}
}
回答by tomfumb
Surely it's a little extreme to say
这么说肯定有点极端
...never use a for in loop to enumerate over an array. Never. Use good old for(var i = 0; i<arr.length; i++)
...永远不要使用 for in 循环来枚举数组。绝不。使用旧的 for(var i = 0; i<arr.length; i++)
?
?
It is worth highlighting the section in the Douglas Crockford extract
值得强调道格拉斯·克罗克福德 (Douglas Crockford) 摘录中的部分
...The second form should be used with objects...
...第二种形式应与对象一起使用...
If you require an associative array ( aka hashtable / dictionary ) where keys are named instead of numerically indexed, you will have to implement this as an object, e.g. var myAssocArray = {key1: "value1", key2: "value2"...};.
如果您需要一个关联数组(又名哈希表/字典),其中键被命名而不是数字索引,则必须将其实现为一个对象,例如var myAssocArray = {key1: "value1", key2: "value2"...};.
In this case myAssocArray.lengthwill come up null (because this object doesn't have a 'length' property), and your i < myAssocArray.lengthwon'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.
在这种情况下myAssocArray.length会出现 null(因为这个对象没有 'length' 属性),并且你i < myAssocArray.length不会走得太远。除了提供更大的便利之外,我希望关联数组在许多情况下提供性能优势,因为数组键可以是有用的属性(即数组成员的 ID 属性或名称),这意味着您不必遍历冗长的数组反复评估 if 语句以找到您所追求的数组条目。
Anyway, thanks also for the explanation of the JSLint error messages, I will use the 'isOwnProperty' check now when interating through my myriad associative arrays!
无论如何,还要感谢对 JSLint 错误消息的解释,当我通过无数关联数组进行交互时,我现在将使用“isOwnProperty”检查!
回答by Benno
Just to add on to the topic of for in/for/$.each, I added a jsperf test case for using $.each vs for in: http://jsperf.com/each-vs-for-in/2
只是为了添加到 for in/for/$.each 的主题,我添加了一个 jsperf 测试用例,用于使用 $.each 与 for in:http://jsperf.com/each-vs-for-in/2
Different browsers/versions handle it differently, but it seems $.each and straight out for in are the cheapest options performance-wise.
不同的浏览器/版本以不同的方式处理它,但似乎 $.each 和直接输入是性能方面最便宜的选项。
If you're using for in to iterate through an associative array/object, knowing what you're after and ignoring everything else, use $.each if you use jQuery, or just for in (and then a break; once you've reached what you know should be the last element)
如果您使用 for in 遍历关联数组/对象,知道您在追求什么并忽略其他所有内容,请使用 $.each 如果您使用 jQuery,或者只是 for in (然后休息;一旦你达到你所知道的应该是最后一个元素)
If you're iterating through an array to perform something with each key pair in it, should use the hasOwnProperty method if you DON'T use jQuery, and use $.each if you DO use jQuery.
如果您正在遍历数组以使用其中的每个密钥对执行某些操作,如果您不使用 jQuery,则应使用 hasOwnProperty 方法,如果您使用 jQuery,则应使用 $.each。
Always use for(i=0;i<o.length;i++)if you don't need an associative array though... lol chrome performed that 97% faster than a for in or $.each
for(i=0;i<o.length;i++)如果您不需要关联数组,请始终使用...大声笑 chrome 的执行速度比 for in 快 97% 或$.each
回答by Fabien Ménager
This means that you should filter the properties of evtListeners with the hasOwnProperty method.
这意味着您应该使用hasOwnProperty 方法过滤 evtListeners 的属性。

