Javascript 为什么要使用;为了……在“中”;对于数组迭代是个坏主意吗?

Javascript 为什么要使用;为了……在“中”;对于数组迭代是个坏主意吗?,javascript,arrays,loops,for-loop,iteration,Javascript,Arrays,Loops,For Loop,Iteration,我被告知不要在JavaScript数组中使用for…in。为什么不呢?因为它通过对象字段而不是索引进行枚举。您可以使用索引“length”获取值,我怀疑您是否需要它。因为它通过对象字段而不是索引进行枚举。您可以使用索引“length”获取值,我怀疑您是否需要此值。原因是一个构造: var a=[];//创建一个新的空数组。 a[5]=5;//调整数组大小的完全合法的JavaScript。 对于(变量i=0;i

我被告知不要在JavaScript数组中使用
for…in
。为什么不呢?

因为它通过对象字段而不是索引进行枚举。您可以使用索引“length”获取值,我怀疑您是否需要它。

因为它通过对象字段而不是索引进行枚举。您可以使用索引“length”获取值,我怀疑您是否需要此值。

原因是一个构造:

var a=[];//创建一个新的空数组。
a[5]=5;//调整数组大小的完全合法的JavaScript。
对于(变量i=0;i*/
原因是一种构造:

var a=[];//创建一个新的空数组。
a[5]=5;//调整数组大小的完全合法的JavaScript。
对于(变量i=0;i*/
因为for…in通过保存数组的对象而不是数组本身进行枚举。如果我在arrays原型链中添加一个函数,它也将包括在内。即

Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
 document.write(x + ' = ' + a[x]);
}
这将写:

0 = foo 1 = bar myOwnFunction = function() { alert(this); } 0 = foo 1 = bar 0=foo 1=巴 myOwnFunction=function(){alert(this);} 由于您永远无法确定不会向原型链添加任何内容,因此只需使用for循环来枚举数组:

for(i=0,x=a.length;i<x;i++){
 document.write(i + ' = ' + a[i]);
}

for(i=0,x=a.length;i,因为for…in通过保存数组的对象枚举,而不是数组本身。如果我向数组原型链添加函数,也将包括该函数。即

Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
 document.write(x + ' = ' + a[x]);
}
这将写:

0 = foo 1 = bar myOwnFunction = function() { alert(this); } 0 = foo 1 = bar 0=foo 1=巴 myOwnFunction=function(){alert(this);} 由于您永远无法确定不会向原型链添加任何内容,因此只需使用for循环来枚举数组:

for(i=0,x=a.length;i<x;i++){
 document.write(i + ' = ' + a[i]);
}

for(i=0,x=a.length;i在单独情况下,在数组上使用for-In没有错。for-In迭代对象的属性名称,在“开箱即用”数组的情况下,属性对应于数组索引。(迭代中不包括内置属性,如
length
toString
等。)

但是,如果您的代码(或您正在使用的框架)将自定义属性添加到阵列或阵列原型中,那么这些属性将包含在迭代中,这可能不是您想要的

一些JS框架,比如Prototype,会修改数组原型,而其他框架,比如JQuery,则不会,因此使用JQuery,您可以安全地在中使用

如果您有疑问,您可能不应该在中使用

迭代数组的另一种方法是使用for循环:

for (var ix=0;ix<arr.length;ix++) alert(ix);

然后数组有两个项,但长度为101。使用for-in将产生两个索引,而for循环将产生101个索引,其中99的值为
未定义的
,,在数组上使用for-in没有错。for-in迭代对象的属性名,如果是“开箱即用”数组,属性对应于数组索引。(迭代中不包括内置属性,如
length
toString
等。)

但是,如果您的代码(或您正在使用的框架)将自定义属性添加到阵列或阵列原型中,那么这些属性将包含在迭代中,这可能不是您想要的

一些JS框架,比如Prototype,会修改数组原型,而其他框架,比如JQuery,则不会,因此使用JQuery,您可以安全地在中使用

如果您有疑问,您可能不应该在中使用

迭代数组的另一种方法是使用for循环:

for (var ix=0;ix<arr.length;ix++) alert(ix);

然后数组有两个项,但长度为101。使用for in将产生两个索引,而for循环将产生101个索引,其中99的值为
未定义
有三个原因不应该使用
for..in
来迭代数组元素:

  • for..in
    将循环遍历数组对象的所有自己的和继承的属性,这些属性不是
    DontEnum
    ;这意味着如果有人向特定数组对象添加属性(这是有正当理由的-我自己这样做了)或更改了
    array.prototype
    (这被认为是与其他脚本协同工作的代码中的错误做法),这些属性也将被迭代;通过检查
    hasOwnProperty()
    ,可以排除继承的属性,但这对数组对象本身中设置的属性没有帮助

  • for..in
    不能保证保留元素顺序

  • 这很慢,因为您必须遍历数组对象及其整个原型链的所有属性,并且仍然只能获取属性的名称,也就是说,要获取值,需要进行额外的查找


有三个原因不应该使用
for..in
来迭代数组元素:

  • for..in
    将循环遍历数组对象的所有自己的和继承的属性,这些属性不是
    DontEnum
    ;这意味着如果有人向特定数组对象添加属性(这是有正当理由的-我自己这样做了)或更改了
    array.prototype
    (这被认为是与其他脚本协同工作的代码中的错误做法),这些属性也将被迭代;通过检查
    hasOwnProperty()
    ,可以排除继承的属性,但这对数组对象本身中设置的属性没有帮助

  • for..in
    不能保证保留元素顺序

  • 这很慢,因为您必须遍历数组对象的所有属性
    ii = parseInt(ii);
    
    var array = [];
    array[2] = 'c';
    array[1] = 'b';
    array[0] = 'a';
    
    for (var p in array) {
      //... p will be "2", "1" and "0" on IE
    }
    
    Array.prototype.last = function () { return this[this.length-1]; };
    
    for (var p in []) { // an empty array
      // last will be enumerated
    }
    
    for (var prop in obj) {
      if (obj.hasOwnProperty(prop)) {
        // prop is not inherited
      }
    }
    
    for (var prop in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, prop)) {
        // prop is not inherited
      }
    }
    
    var arr = ['a','b','c'];
    for (var key in arr) { ... }
    
    //Non-associative
    var arr = ['a', 'b', 'c'];
    for (var i in arr)
       alert(arr[i]);
    
    //Associative
    var arr = {
       item1 : 'a',
       item2 : 'b',
       item3 : 'c'
    };
    
    for (var i in arr)
       alert(arr[i]);
    
    var a = ["a"]
    for (var i in a)
        alert(typeof i)  // 'string'
    for (var i = 0; i < a.length; i++)
        alert(typeof i)  // 'number'
    
    myobject.propertyIsEnumerable('myproperty')
    
    Object.getOwnPropertyDescriptor(myobject,'myproperty')
    
    // C#
    char[] a = new char[] {'A', 'B', 'C'};
    foreach (char x in a) System.Console.Write(x); //Output: "ABC"
    
    // Java
    char[] a = {'A', 'B', 'C'};
    for (char x : a) System.out.print(x);          //Output: "ABC"
    
    // PHP
    $a = array('A', 'B', 'C');
    foreach ($a as $x) echo $x;                    //Output: "ABC"
    
    // JavaScript
    var a = ['A', 'B', 'C'];
    for (var x in a) document.write(x);            //Output: "012"
    
    Array.prototype.someProperty = true
    
    for(var item in [1,2,3]){
      console.log(item) // will log 1,2,3 but also "someProperty"
    }
    
    var ary = [1,2,3];
    for(var item in ary){
       if(ary.hasOwnProperty(item)){
          console.log(item) // will log only 1,2,3
       }
    }
    
    for (var item of items) {
        console.log(item);
    }
    
    Array.prototype.foo = 1;
    var arr = [];
    arr[5] = "xyz";
    
    console.log("for...of:");
    var count = 0;
    for (var item of arr) {
        console.log(count + ":", item);
        count++;
        }
    
    console.log("for...in:");
    count = 0;
    for (var item in arr) {
        console.log(count + ":", item);
        count++;
        }
    
    for...of:
    
    0: undefined
    1: undefined
    2: undefined
    3: undefined
    4: undefined
    5: xyz
    
    for...in:
    
    0: 5
    1: foo
    
    var arr = [];
    arr[5] = 'F';
    
    for (var index in arr) {
    console.log(index);
    console.log(arr[index]);
    console.log(arr)
    }
    // 5
    // 'F'
    // => (6) [undefined x 5, 6]
    
    arr.forEach(function(element, index, arr) {
    console.log(index);
    console.log(element);
    console.log(arr);
    });
    // 5
    // 'F'
    // => Array (6) [undefined x 5, 6]
    
    for (var index = 0; index < arr.length; index++) {
    console.log(index);
    console.log(arr[index]);
    console.log(arr);
    };
    // 0
    // undefined
    // => Array (6) [undefined x 5, 6]
    
    // 1
    // undefined
    // => Array (6) [undefined x 5, 6]
    
    // 2
    // undefined
    // => Array (6) [undefined x 5, 6]
    
    // 3
    // undefined
    // => Array (6) [undefined x 5, 6]
    
    // 4
    // undefined
    // => Array (6) [undefined x 5, 6]
    
    // 5
    // 'F'
    // => Array (6) [undefined x 5, 6]
    
    let txt = "";
    const person = {fname:"Alireza", lname:"Dezfoolian", age:35}; 
    for (const x in person) {
        txt += person[x] + " ";
    }
    console.log(txt); //Alireza Dezfoolian 35 
    
    let txt = "";
    const person = ["Alireza", "Dezfoolian", 35]; 
    for (const x in person) {
       txt += person[x] + " ";
    }
    console.log(txt); //Alireza Dezfoolian 35 
    
    Array.prototype.someoneelse = "someoneelse";
    
    let txt = "";
    const arr = new Array();
    arr[0] = 'Alireza';
    arr[1] = 'Dezfoolian';
    arr[2] = 35;
    for(x in arr) {
     txt += arr[x] + " ";
    }
    console.log(txt); //Alireza Dezfoolian 35 someoneelse
    
    var myArray = ['a', 'b', 'c', 'd'];
    var total = 0
    for (elem in myArray) {
      total += elem
    }
    console.log(total); // 00123
    
    var nodes = document.querySelectorAll(selector);
    nodes
    ▶ NodeList [a._19eb]
    for (node in nodes) {console.log(node)};
    VM505:1 0
    VM505:1 length
    VM505:1 item
    VM505:1 entries
    VM505:1 forEach
    VM505:1 keys
    VM505:1 values