方法一:自定义Symbol.iterator属性
如果对象拥有[Symbol.iterator]
方法,改方法返回一个迭代器对象,就可以称之为可迭代对象,注意迭代器是一个有 next 方法的对象
步骤如下
- 实现一个Symbol.iterator 键
- 值是一个函数,函数返回一个迭代器
- 迭代器是一个对象,对象里有一个next方法
- next 方法按照条件返回 {value, done} 的对象
const obj = {name: 'name value',age: 'age value'
}
// 实现一个Symbol.iterator 键
// 值是一个函数,函数返回一个迭代器
// 迭代器是一个对象,对象里有一个next方法
// next 方法按照条件返回 {value, done} 的对象
obj[Symbol.iterator] = function () {const keys = Object.keys(this)let index = 0return {// 一定要使用箭头函数,要不下面的this 不对next: ()=> {if (index < keys.length) {return {// index++ 使用,这条语句结束后再 +1value: this[keys[index++]],done: false}}return {done: true}}}
}
for (let i of obj) {console.log(i) // 这个打印的是 value的值 ,name value, age value
}
// 显式调用
console.log(obj[Symbol.iterator]().next().value)
方法二:使用生成器
生成器真好用
const obj = {name: 'name value',age: 'age value'
}
// function 和函数名之间加一个星号就是一个生成器函数
function* toIterator(obj) {let keys = Object.keys(obj)for (let key of keys) {// 原理是生成器中// 每调用一次遇到 yield 都会停止,并返回【迭代器对象的状态】// 【迭代器对象的状态】是一个对象,{ value:'xx', done: true/false }// 并将 yield 后面的那个【表达式的值】,作为返回的对象的 value 属性值// 如果没有 yield 就会一直运行到函数结束,直到 return 语句// 并将 return 语句后面的表达式值,作为 value// 如果没有 return 语句,则返回的 value 为 undefinedyield obj[key] // 可以自定义遍历的值,这里是 obj 的 value}
}
// 变成可迭代对象
const newObj = toIterator(obj)
// 使用 for of 遍历
for (let i of newObj) {console.log(i) // name value , age value
}