for-in和for-of

379 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

遍历对象

for-in

当我们用for-in来遍历一个对象的时候,结果打印的是对象里面的键

const obj={
    a:1,
    b:2,
    c:3
}
for(let key in obj){
    console.log(key);   //可以直接帮我们拿到对象里面的 key
}
//a
//b
//c

for-of

然鹅当我们用for-of来遍历对象的时候,我们就会发现有错误出现:

const obj={
    a:1,
    b:2,
    c:3
}
for(let i of obj){   
    console.log(i);
}
//TypeError: obj is not iterable

如果我们这样打印就会发现会有错误提示:TypeError: obj is not iterable 这个的意思就是obj这个对象不是可迭代的,这就说明for-of循环的值必须是一个iterable(就是一个能产生迭代器供循环使用的对象)

遍历数组

for-in

而当我们用for-in来遍历一个数组的时候,结果打印的是数组的下标

const arr=['a','b','c','d']
for(let i in arr){
    console.log(i);  
}
// 0 1 2 3

for-of

当我们用for-of遍历数组会打印数组的元素

const arr=['a','b','c','d']
for(let i of arr){
    console.log(i);  
}
// a b c d

for-in可以访问到原型里面的属性

当我们往对象的原型里面添加一个属性,可以通过for-in访问到

const obj1={
    a:1,
    b:2,
    c:3
}
for(let i in obj1){
    console.log(i);
}
//此时打印的是a b c
Object.prototype.d=4
for(let i in obj1){
    console.log(i);  //a b c d
}
//a b c d

for-of

并且用for-in遍历的对象的数字属性会被优先遍历,并且是按照数字的大小顺序遍历

function Foo(){
    this[100]='test-100'
    this[22]='test-22'
    this['b']='test-b'
    this['m']='test=m'
    this[1]='test-1'
    this['a']='test-a'
}
let bar=new Foo()
for(let key in bar){
    console.log(`index:${key} value:${bar[key]}`);
}

// index:1 value:test-1
// index:22 value:test-22
// index:100 value:test-100
// index:b value:test-b
// index:m value:test=m
// index:a value:test-a
// index:d value:4

这是因为ECMAScript规范定义了数字属性应该按照索引值的大小顺序排列,而字符串属性根据创建时的属性顺序排列

总结

for in

  1. 返回的都是数据结构的键名
  2. 遍历数组返回的是下标
  3. 还会遍历到原型(内置的属性不会)上的属性值,for of 不会
  4. 遍历对象得到的属性值顺序可能和元对象的属性值顺序不相同

for of

  1. 只能遍历具有 iterable 属性的数据结构 //然而for in能遍历所有的 天生具有迭代器接口的数据结构如下: Array Map Set String TypedArray 函数的arguments对象 NodeList对象
  2. 不会遍历到原型上的属性