JSLint错误'for的主体应该包含在if语句中'是什么意思?

时间:2009-12-26 10:49:40

标签: javascript jslint

我在我的JavaScript文件中使用了JSLint。它抛出了错误:

for( ind in evtListeners ) {
  

第41行的问题第9条:for的身体应该是   包含在if语句中以过滤不需要的   原型中的属性。

这是什么意思?

7 个答案:

答案 0 :(得分:404)

首先,从不使用for in循环来枚举数组。决不。使用好的旧for(var i = 0; i<arr.length; i++)

背后的原因如下: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]

这是扩展对象和添加新方法的标准方法。很多图书馆都这样做。 但是,让我们看看for in现在如何运作:

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方法,它检查这个字段是否真的属于对象本身,或者它是否只是从原型链继承而来,因此属于该类型的所有对象。

for (o in listeners) {
    if (listeners.hasOwnProperty(o)) {
       console.log(o);
    }
}
 //prints:
 //  0
 //  1
 //  2

请注意,尽管此代码的工作方式与数组一致,但您绝不应该永远,对数组使用for infor 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

答案 1 :(得分:85)

jslint的作者道格拉斯·克罗克福德曾多次撰写(和发言)这个问题。他网站的this页面上有一节介绍了这一点:

  

for Statement

     

一类陈述应该有   以下表格:

for (initialization; condition; update) {
    statements
}

for (variable in object) {
    if (filter) {
        statements
    } 
}
     

第一个表格应该与。一起使用   数组和一个循环   可预先确定的迭代次数。

     

第二种形式应该与   对象。请注意那些成员   被添加到原型中   对象将被包含在   列举。编程是明智的   在防守上使用   hasOwnProperty方法来区分   对象的真正成员:

for (variable in object) {
    if (object.hasOwnProperty(variable)) {
        statements
    } 
}

Crockford还有一个关于YUI剧院的视频系列,在那里他谈到这一点。如果你对javascript稍微认真一点,Crockford关于javascript的一系列视频/谈话是必须要看的。

答案 2 :(得分:9)

Vava的回答是正确的。如果您使用jQuery,那么$.each()函数会处理这个问题,因此使用起来更安全。

$.each(evtListeners, function(index, elem) {
    // your code
});

答案 3 :(得分:7)

@all - JavaScript中的所有东西都是一个object(),所以像“只在对象上使用它”之类的语句有点误导。另外JavaScript不是强类型的,因此1 ==“1”为真(虽然1 ===“1”不是,Crockford对此很重要)。当谈到JS中数组的概念性概念时,在定义中输入很重要。

@Brenton - 不需要成为术语独裁者; “关联数组”,“字典”,“哈希”,“对象”,这些编程概念都适用于JS中的一个结构。它是名称(键,索引)值对,其中值可以是任何其他对象(字符串也是对象)

所以, new Array()[]

相同

new Object(){}

大致相似
var myarray = [];

创建一个数组结构,其限制是所有索引(也称为键)必须是整数。它还允许通过.push()

自动分配新索引
var myarray = ["one","two","three"];

确实最好通过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]);
    }
}

答案 4 :(得分:2)

当然,说起来有点极端

  

...永远不要使用for循环   枚举数组。决不。使用   (var i = 0;   I&LT; arr.length;我++)

值得强调道格拉斯克罗克福德提取物中的部分

  

......第二种形式应该与。一起使用   对象...

如果需要一个关联数组(也就是哈希表/字典),其中键被命名而不是数字索引,则必须将其作为对象实现,例如var myAssocArray = {key1: "value1", key2: "value2"...};

在这种情况下,myAssocArray.length将显示为null(因为此对象没有'length'属性),并且您的i < myAssocArray.length不会让您走得太远。除了提供更大的便利之外,我希望关联数组在许多情况下提供性能优势,因为数组键可以是有用的属性(即数组成员的ID属性或名称),这意味着您不必迭代冗长数组重复评估if语句以查找您所追求的数组条目。

无论如何,还要感谢JSLint错误消息的解释,我将在通过我的无数关联数组进行交互时使用'isOwnProperty'检查!

答案 5 :(得分:0)

这意味着您应该使用hasOwnProperty method过滤evtListeners的属性。

答案 6 :(得分:0)

为了补充in / for / $。each的主题,我添加了一个jsperf测试用例,用于使用$ .each vs for:http://jsperf.com/each-vs-for-in/2

不同的浏览器/版本以不同的方式处理它,但似乎$ .each和直接输入是性能最便宜的选项。

如果你正在使用in来迭代一个关联数组/对象,知道你在追求什么并忽略其他一切,如果你使用jQuery,则使用$ .each,或者只使用in(然后中断;一次;你达到了你应该知道的应该是最后一个元素)

如果你正在迭代一个数组来执行其中每个键对的某些事情,如果你不使用jQuery则应该使用hasOwnProperty方法,如果你使用jQuery则使用$ .each。

如果您不需要关联数组,请始终使用for(i=0;i<o.length;i++) ... lol chrome的执行速度比in $.each快97%