for in和for of对比

不同点:
时间点不同:for in 在js出现之初就有,for of出现在ES6之后
遍历的内容不同:for in用于遍历对象的可枚举属性(包括原型链上的可枚举属性),for of用于遍历可迭代对象的值

看个例子

// for in
const arr = ['a','b','c','d']
for(const index in arr) {
  console.log(index) 
}
// 打印结果:'0' '1' '2' '3',可以发现打印的是数组的下标,数组是特殊的对象,下标是数组对象身上的可枚举属性,打印的就是这个可枚举属性

// for of
for(const item of arr) {
  console.log(item)
}
// 打印结果:'a' 'b' 'c' 'd',for of打印的就是数组里的每一项元素的值

可枚举属性
通过Object.getOwnPropertyDescriptor(obj, property),可以拿到属性描述符

// 还是以数组为例,获取数组的属性'0'
console.log(Object.getOwnPropertyDescriptor(['a'],'0'))
/**
 * {
 *   configurable: true,
 *   enumerable: true,
 *   value: "a",
 *   writable: true
 * }
 */
/* 可以看到返回了一个对象,这个对象就是属性描述符,属性描述符的属性一般被称为特性,可以看到,第二个特性enumerable就代表属性是否可枚举
   可枚举的属性就可以通过for in与Object.keys遍历,数组身上有一个length属性,但上面我们用for in 循环的时候并没有打印length,说明
   length属性是一个不可枚举属性,我们来看一下length属性的属性描述符:
*/
console.log(Object.getOwnPropertyDescriptor(['a'],'length'))
/**
 * {
 *   configurable: false,
 *   enumerable: false,
 *   value: 1,
 *   writable: true
 * }
 */
// 可以看到数组身上的length属性的属性描述符里,enumerable为false,它是一个不可枚举属性,属性描述符还有其他的特性,此处就不展开描述了,感兴趣可以自行查阅

可迭代对象
实现了[Symbol.iterator]方法的对象,就被称为可迭代对象
对象进行for…of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)
链接: link

const obj = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};

上面的代码中,对象obj是可遍历的(iterable),因为具有Symbol.iterator属性。执行这个属性,会返回一个遍历器对象。该对象的根本特征就是具有next方法。每次调用next方法,都会返回一个代表当前成员的信息对象,具有value和done两个属性
所以,对象只要实现了[Symbol.iterator]方法,就是可迭代的,即可使用for…of遍历
原生具备 Iterator 接口的数据结构如下
Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象

案例:数组的Symbol.iterator属性

let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();

iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }

实现[Symbol.iterator]方法好麻烦,怎么这么复杂,于是有Generator 函数
Generator函数可以直接返回一个遍历器对象
由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性,从而使得该对象具有 Iterator 接口

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

[...myIterable] // [1, 2, 3]
for(const item of myIterable){console.log(item)} //1,2,3

上面代码中,Generator 函数赋值给Symbol.iterator属性,从而使得myIterable对象具有了 Iterator 接口,可以被…运算符和for…in遍历了

async await,async await就是生成器函数的语法糖,配合promise,用生成器函数加yield也可以实现async await同样的效果

参考:链接: link
链接: link

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值