在看Generator函数时看到一句话
当调用一个Generator函数时,它并不会立即执行函数体,而是返回一个迭代器对象(Iterator)
然后我搜了一下Symbol.Inerator
Symbol.iterator
是 JavaScript 中的一个内置 Symbol,它代表了一个对象的默认迭代器。当一个对象具有Symbol.iterator
方法时,它就是一个可迭代对象,可以使用for...of
循环或者...
运算符进行迭代。
Symbol.iterator
方法返回一个迭代器对象,该迭代器对象有一个next()
方法,每次调用next()
方法都会返回一个包含value
和done
两个属性的对象。其中value
表示当前迭代到的值,done
表示迭代是否结束。
这里有一句话 “它就是一个可迭代对象,可以使用 for...of
循环或者 ...
运算符进行迭代”,嗯?只要又了Symbol.Inerator就可以去循环和扩展运算了吗,然后我尝试把一个Generator函数调用的使用...扩展打印,发现时确实就像数组一样
然后我搜了一下关于JS中...扩展运算符的原理
JS中
...
的原理是使用迭代器(Iterator)对象来实现的。当使用...
运算符来展开一个可迭代对象时,JS引擎会自动调用该对象的[Symbol.iterator]()
方法,获取该对象的迭代器对象(Iterator)。然后通过不断调用迭代器对象的next()
方法来获取可迭代对象中的每个元素,直到迭代器对象返回{ done: true }
表示迭代结束
...的原理其实就是在该数据的原型链上查找[Symbol.iterator]这个方法,在找到这个方法会调用里面.next方法,接着判断return值中是否有value和done,当done为true时停止,并且不记录done为true时这一次的值
抱着来都来了的想法我尝试去改变Array的迭代器并且在Object上添加一个迭代器
改变Array上面的迭代器让 ...扩展运算符显示自定义内容
Array.prototype[Symbol.iterator] = function() {
let index = 0; // 当前下标
const that = this;
return {
next: () => {
return { value: '自定义内容', done: that.length === index++ } // 先判断是否为最后一个再自增
}
}
};
let arr = [1, 2, 3, 4, 5];
[...arr]; // ['自定义内容', '自定义内容', '自定义内容', '自定义内容', '自定义内容']
给Object类型添加一个迭代器,让Object类型也能使用扩展运算符
Object.prototype[Symbol.iterator] = function() {
const that = this;
const keys = Object.keys(that);
let index = 0;
return {
next: () => {
const key = keys[index++];
return { value: that[key], done: keys.length === index - 1 } // 这里index是自增后的数据所以-1
}
}
}
let obj = { code: 200, data: [], message: '操作成功' };
[...obj] // [200, [], '操作成功']
总结
JS中的...扩展运算符会在原型链上找是否有Symbol.iterator这个迭代器,如果有则调用next方法,next方法需要返回一个对象上面需要有value和done,value就是当前值,done表示是否完成,done为true的那一次结果不会使用