Open wang1dot0 opened 5 years ago
var obj = { a: 1, b: 11, c: 22 }; [...obj]
结果: 因为[...iterat]中iterat必须是可迭代的iterable,而对象默认并不是迭代器,所以,会报错。而默认提供iterable接口的有数组,字符串和新加入的Set和Map等。 它的实现是内置了@@iterator对象,我们可以通过调用[Symbol.iterator]方法访问。 因此,要实现上述功能:
Object.defineProperty(obj, Symbol.iterator, { writable: true, configuable: true, value: function () { let _copy = this, keys = Object.keys(_copy), i = 0; return { next() { let res = _copy[keys[i++]]; if (i === keys.length) { return { value: undefined, done: true }; } return { value: res, done: false }; }, }; }, });
缺点很明显,比较臃肿,而且还丑陋地锁定this的指向。 方法二 obj[Symbol.iterator] = function *foo() { const arr = Object.keys(this);
缺点很明显,比较臃肿,而且还丑陋地锁定this的指向。
obj[Symbol.iterator] = function *foo() { const arr = Object.keys(this);
for (idx of arr) { yield this[idx]; } }
> 明显利用了generator/yield本身也是一个迭代器的特性,比方法一简化了很多。 #### 方法三 ```js obj[Symbol.iterator] = function *foo() { var arr = Object.values(this); yield *arr; }
发现yield *的用法,它是一种委托,如果后面跟的是一个迭代器,它会默认委托执行该迭代器,于是有了上面的方法。
结果: 因为[...iterat]中iterat必须是可迭代的iterable,而对象默认并不是迭代器,所以,会报错。而默认提供iterable接口的有数组,字符串和新加入的Set和Map等。 它的实现是内置了@@iterator对象,我们可以通过调用[Symbol.iterator]方法访问。 因此,要实现上述功能:
方法一
for (idx of arr) { yield this[idx]; } }