在 ES6 中,引入了迭代器(Iterator)和 for...of 循环,让我们可以更方便地遍历数据结构。但是,ES6 的迭代器只能遍历内置的数据结构,如数组、Map、Set 等。如果我们想要遍历自定义的数据结构,该怎么办呢?这时候就需要使用 Symbol。
Symbol 是 ES6 引入的一种新的原始数据类型,它可以用来创建唯一的值。在 ES8/ES2017 中,Symbol 有了更多的用途,其中之一就是用来实现自定义迭代器。
Symbol.iterator
在 ES6 中,内置的数据结构都有一个默认的迭代器,可以通过 Symbol.iterator 属性访问到。例如,数组的迭代器可以通过以下方式获取:
const arr = [1, 2, 3]; const iterator = arr[Symbol.iterator]();
当我们调用数组的迭代器时,会返回一个迭代器对象,该对象有一个 next() 方法,每次调用该方法都会返回一个包含 value 和 done 两个属性的对象。value 表示当前迭代到的值,done 表示是否已经遍历完了所有值。
console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
实现自定义迭代器
现在,我们来看一下如何通过 Symbol 实现自定义迭代器。假设我们有一个自定义的数据结构,它是一个对象数组,每个对象都有一个 name 属性和一个 age 属性。我们想要实现一个迭代器,可以遍历这个数组中所有对象的 name 属性。
首先,我们需要在数据结构上定义一个 Symbol.iterator 方法,该方法返回一个迭代器对象。迭代器对象需要有一个 next() 方法,每次调用该方法都会返回一个包含 value 和 done 两个属性的对象。value 表示当前迭代到的值,done 表示是否已经遍历完了所有值。
// javascriptcn.com 代码示例 const people = [ { name: 'Alice', age: 20 }, { name: 'Bob', age: 30 }, { name: 'Charlie', age: 40 } ]; people[Symbol.iterator] = function() { let index = 0; return { next: function() { if (index < people.length) { return { value: people[index++].name, done: false }; } else { return { value: undefined, done: true }; } } }; };
在上面的代码中,我们给 people 数组定义了一个 Symbol.iterator 方法,该方法返回一个包含 next() 方法的对象。next() 方法中,我们通过 index 变量来记录当前迭代到的位置,每次调用 next() 方法时,如果还有值未遍历,则返回该值的 name 属性,否则返回 undefined 和 true。
现在,我们就可以使用 for...of 循环来遍历 people 数组中所有对象的 name 属性了。
for (const name of people) { console.log(name); } // Alice // Bob // Charlie
总结
通过 Symbol,我们可以实现自定义的迭代器,让我们可以更方便地遍历自定义的数据结构。在实现自定义迭代器时,我们需要在数据结构上定义一个 Symbol.iterator 方法,该方法返回一个迭代器对象,该对象有一个 next() 方法,每次调用该方法都会返回一个包含 value 和 done 两个属性的对象。通过这种方式,我们可以让我们的数据结构支持 for...of 循环等操作,让代码更加简洁易读。
示例代码
// javascriptcn.com 代码示例 const people = [ { name: 'Alice', age: 20 }, { name: 'Bob', age: 30 }, { name: 'Charlie', age: 40 } ]; people[Symbol.iterator] = function() { let index = 0; return { next: function() { if (index < people.length) { return { value: people[index++].name, done: false }; } else { return { value: undefined, done: true }; } } }; }; for (const name of people) { console.log(name); } // Alice // Bob // Charlie
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/656555dbd2f5e1655de98ff0