for in
for in 使用于可枚举的数据 如 对象 数组 字符串
什么是可枚举的:属性的enumerable值为true,表示可枚举
可以通过es7新增的属性 Object.getOwnPropertyDescriptors()验证 查看
Object.getOwnPropertyDescriptor() 方法用于 返回 指定 对象 上一个自有 属性 对应的属性描述符
// 通过Object.getOwnPropertyDescriptors()
const a = [1, 23, 3]
console.log(Object.getOwnPropertyDescriptors(a));
const b = { a: 1, b: 2 }
console.log(Object.getOwnPropertyDescriptors(b));
const c = 'string'
console.log(Object.getOwnPropertyDescriptors(c));
看下图打印的信息,enumerable值为true表示都是可迭代对象
for in 不仅能便利自身的属性,他还能便利原型链上可枚举的属性
他返回的是key的值,并且不能保证顺序
let a = [1,2,3]
Array.prototype.num = 4
for(let i in a){
console.log(i) // 0,1,2,num
console.log(a[i]) // 1,2,3,4
}
// 他返回的是value的值
for(let j of a){
console.log(j) // 1,2,3
}
for of
for of 适用于可迭代数据
什么是可迭代数据 :在原型链上具有Symbol.iterator属性,通过调用.next() 方法,返回对应的属性
可迭代数据:array string Map Set 函数的arguments对象 还有我们的生成器函数function*( ){ }
const a = [1,2,3]
//a.prototype上有这么一个属性 Symbol(Symbol.iterator):ƒ values() 表示可迭代的
同理 string Map Set 这些原型上都有这个属性
for of 只能便利自身的属性
他得到的是value 具体和迭代器的内部实现有关
const arr = [1, 2, 3]
arr[Symbol.iterator] = function () {
const that = this
return {
i: 0,
next() {
// 正常的 通过 for of 返回value
return this.i < that.length ? { value: that[this.i++], done: false } : { value: undefined, done: true }
}
}
}
for (let i of arr) {
console.log(i); // 1,2,3
}
// 改写Symbol.iterator的next方法
arr[Symbol.iterator] = function () {
const that = this
return {
i: 0,
next() {
// 通过改写之后 for of也能返回key
return this.i < that.length ? { value: this.i++, done: false } : { value: undefined, done: true }
}
}
}
for (let i of arr) {
console.log(i); // 0,1,2 输出的是key
}