在我们日常的开发中,遍历某个 数据 / 值 是随时随地都会遇到的一种需求,js可实现遍历的方法多种多样,今天我们就来详细聊聊 for in 和 for of
for in 和 for of 简单来说就是它们两者都可以用于遍历,可能大部分人觉得比较简单,都差不了多少,也没有对这两种方法做一个详细的区分,今天我们就来学习总结一下。
首先,在MDN官网就说明了 for...of与for...in的区别 ,有兴趣的伙伴可以去官网再仔细研究一下
for in 和 for of 的本质区别
1、使用的目标不一样
1-1、for in 适用于 可枚举属性,例如 对象、数组、字符串。
那么什么是可枚举属性呢?
属性的 enumerable 值为 true 就为可枚举的,通过Object.getOwnPropertyDescriptors() 或 Object.prototype.propertyIsEnumerable() 进行查看 / 验证
const obj = {
name: 'zhangsan',
age: 18
}
console.log(Object.getOwnPropertyDescriptors(obj))
// {
// name: { value: 'zhangsan', writable: true, enumerable: true, configurable: true },
// age: { value: 18, writable: true, enumerable: true, configurable: true }
// }
const arr = [1, 2, 3]
console.log(Object.getOwnPropertyDescriptors(arr))
// {
// '0': { value: 1, writable: true, enumerable: true, configurable: true },
// '1': { value: 2, writable: true, enumerable: true, configurable: true },
// '2': { value: 3, writable: true, enumerable: true, configurable: true },
// length: { value: 3, writable: true, enumerable: false, configurable: false }
// }
const str = 'abc'
console.log(Object.getOwnPropertyDescriptors(str))
// {
// '0': { value: 'a', writable: false, enumerable: true, configurable: false},
// '1': { value: 'b', writable: false, enumerable: true, configurable: false },
// '2': { value: 'c', writable: false, enumerable: true, configurable: false },
// length: { value: 3, writable: false, enumerable: false, configurable: false }
// }
1-2、for of 适用于 可迭代对象,像Array、String、Map、Set、函数的arguments对象、nodeList对象
那么什么是可迭代呢?
ES6中,具有Symbol.iterator 属性,它对应的值是一个函数,调用这个函数后可得到一个对象,每次调用这个对象的next() 方法能得到目标的每一项,只要符合这个特点就是可迭代的
const str = 'zxt'
const it_str = str[Symbol.iterator]()
console.log(it_str.next()) // { value: 'z', done: false }
console.log(it_str.next()) // { value: 'x', done: false }
console.log(it_str.next()) // { value: 't', done: false }
const arr = ['a', 'b']
const it_arr = arr[Symbol.iterator]()
console.log(it_arr.next()) // { value: 'a', done: false }
console.log(it_arr.next()) // { value: 'b', done: false }
2、遍历的范围不一样
for in 能遍历自身的可枚举属性 && 原型上的可枚举属性
for of 一般只能遍历自身的可枚举属性(具体和迭代器内部的实现有关)
我们现在改造 for of 的迭代器,让其也能遍历到原型上可枚举的属性,代码如下:
const arr = [7]
// 在原型上添加属性 foo
Array.prototype.foo = 4
arr[Symbol.iterator] = function() {
const _this = this
Object.keys(this.__proto__).forEach(item => this.push(this.__proto__[item]))
return {
i: 0,
next(){
return this.i < _this.length ? {value: _this[this.i++], done: false} : {value: undefined, done: true}
}
}
}
for(let value of arr) {
console.log(value)
}
// 输出结果 7 4
3、得到的结果不一样
for in 得到的是key(并且不能保证顺序)
for of 一般得到的是value(具体和迭代器内部的实现有关)
我们现在改造 for of 的迭代器,让其遍历也能的是key,代码如下:
const arr = [7, 8]
arr[Symbol.iterator] = function() {
const _this = this
return {
i: 0,
next(){
return this.i < _this.length ? {value: this.i++, done: false} : {value: undefined, done: true}
}
}
}
for(let value of arr) {
console.log(value) // 0 1
}
以上就是我对 for in 和 for of 的总结,如其他小伙伴还有什么问题欢迎评论区留言讨论,谢谢~~