代码之家  ›  专栏  ›  技术社区  ›  jrharshath

for-in的jslin错误体应该用if语句包装,这意味着什么?

  •  225
  • jrharshath  · 技术社区  · 16 年前

    我用过 JSLint 在我的一个javascript文件上。它抛出了错误:

    for( ind in evtListeners ) {
    

    第41行第9个字符的问题:for-in的主体应为 包装在if语句中以筛选不需要的 原型的属性。

    这是什么意思?

    8 回复  |  直到 8 年前
        1
  •  402
  •   Gabriel Nahmias bfavaretto    12 年前

    首先, 从未 使用A 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]
    

    这是扩展对象和添加新方法的标准方法。很多图书馆都这样做。 不过,让我们看看 为了在 现在工作:

    var listeners = ["a", "b", "c"];
    for (o in listeners) {
        console.log(o);
    }
    //prints:
    //  0
    //  1
    //  2
    //  filter_0
    

    你看到了吗?它突然认为过滤器_0是另一个数组索引。当然,它不是真正的数字索引,但是 为了在 通过对象字段枚举,而不仅仅是数字索引。所以我们现在正在枚举每个数字索引 过滤器0 . 但是 过滤器0 不是任何特定数组对象的字段,每个数组对象现在都具有此属性。

    幸运的是,所有对象都有一个 hasOwnProperty 方法,该方法检查此字段是否真正属于对象本身,或者是否只是从原型链继承而来,从而属于该类型的所有对象。

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

    注意,尽管此代码在数组中按预期工作,但您不应该, 从未 ,使用 为了在 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
    
        2
  •  85
  •   Wes Lord Breton    8 年前

    JSlint的作者道格拉斯·克罗克福德(DouglasCrockford)曾多次就这个问题撰文(并发表过意见)。有一部分在 this 他的网站页面包括:

    对于陈述

    for类语句应具有 以下表格:

    for (initialization; condition; update) {
        statements
    }
    
    for (variable in object) {
        if (filter) {
            statements
        } 
    }
    

    第一个表单应与 数组和循环 可预先确定的迭代次数。

    第二个表单应与 物体。注意会员 添加到 对象将包含在 枚举。编程是明智的 通过使用 区分的属性方法 对象的真正成员:

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

    克罗克福德也有一个关于尤伊剧院的视频系列,他在那里谈论这个。Crockford的一系列关于javascript的视频/讨论是一个必须要看你是否对javascript有点认真。

        3
  •  16
  •   wangchi    10 年前

    错误:(JShint将引发错误)

    for (var name in item) {
        console.log(item[name]);
    }
    

    好:

    for (var name in item) {
      if (item.hasOwnProperty(name)) {
        console.log(item[name]);
      }
    }
    
        4
  •  9
  •   HRJ    16 年前

    瓦瓦的回答是正确的。如果使用jquery,则 $.each() 函数处理这个问题,因此使用起来更安全。

    $.each(evtListeners, function(index, elem) {
        // your code
    });
    
        5
  •  7
  •   wade    15 年前

    @所有-javascript中的所有内容都是一个对象(),所以类似“只在对象上使用”这样的语句有点误导性。另外,javascript不是强类型的,所以1==“1”是正确的(尽管1==“1”不是,但crockford在这方面很重要)。当涉及到JS中数组的编程概念时,输入在定义中很重要。

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

    所以, new Array() 是一样的 []

    new Object() 大致类似于 {}

    var myarray = [];
    

    创建一个数组结构,该数组的限制是所有索引(aka键)必须是整数。它还允许通过.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]);
        }
    }
    
        6
  •  2
  •   tomfumb    16 年前

    说起来肯定有点极端

    …永远不要使用for-in循环 枚举数组。从未。使用 适用于(var i=0; i<arr.length;i++)

    ?

    值得一提的是道格拉斯·克罗克福德摘录中的部分。

    …第二个表单应与 物体。。。

    如果您需要一个关联数组(又名hashtable/dictionary),其中键是命名的,而不是数字索引的,那么您必须将其作为一个对象来实现,例如。 var myAssocArray = {key1: "value1", key2: "value2"...}; .

    在这种情况下 myAssocArray.length 将为空(因为此对象没有“length”属性),并且 i < myAssocArray.length 不会让你走很远的。除了提供更大的便利性之外,我还希望关联数组在许多情况下提供性能优势,因为数组键可以是有用的属性(即数组成员的ID属性或名称),这意味着您不必重复使用冗长的数组来计算语句是否要查找尾部的数组条目。呃。

    无论如何,还要感谢对jslint错误消息的解释,我将在通过无数关联数组进行交互时立即使用“isownproperty”检查!

        7
  •  0
  •   Fabien Ménager    16 年前

    这意味着您应该使用 hasOwnProperty method .

        8
  •  0
  •   brbcoding    11 年前

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

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

    如果使用for-in迭代关联数组/对象,知道要搜索的是什么,而忽略了其他所有内容,请使用$。如果使用jquery,则每个都要使用,或者只使用for-in(然后使用break;一旦达到所知道的应该是最后一个元素)

    如果您正在迭代一个数组以对其中的每个键对执行某些操作,那么如果不使用jquery,则应使用hasownproperty方法;如果确实使用jquery,则应使用$.each。

    总是使用 for(i=0;i<o.length;i++) 如果不需要关联数组…lol chrome比for in或 $.each