今天看到一個面試題, 讓下面解構賦值成立。
let [a,b] = {a:1,b:2}
如果我們直接在瀏覽器輸出這行代碼,會直接報錯,說是 {a:1,b:2} 不能迭代。
?看了es6文檔后,具有迭代器的就一下幾種類型,沒有Object類型,不過文檔也解釋為什么沒有給Object加Iterator 接口,原因是?對象(Object)之所以沒有默認部署 Iterator 接口,是因為對象的哪個屬性先遍歷,哪個屬性后遍歷是不確定的,需要開發者手動指定。本質上,遍歷器是一種線性處理,對于任何非線性的數據結構,部署遍歷器接口,就等于部署一種線性轉換。不過,嚴格地說,對象部署遍歷器接口并不是很必要,因為這時對象實際上被當作 Map 結構使用,ES5 沒有 Map 結構,而 ES6 原生提供了。
原生具備 Iterator 接口的數據結構如下。
- Array
- Map
- Set
- String
- TypedArray
- 函數的 arguments 對象
- NodeList 對象
所以,我們回頭看這道面試題,是不是只要給這個{a:1,b:2}加上一個迭代器函數就可以了。
?let [a,b] = {a:1,b:2}
這里我們看下迭代器是什么使用的,在es6里有一個??Symbol.iterator 屬性,只要有這個屬性,那么這個數據結構就是可以遍歷的。下面這個arr是一個Array類型,那么Array本身就帶迭代屬性,而解構就是把迭代的遍歷器對象 的next()返回的value賦值給變量。
let arr = ['1', '2', 'c3];
let iter = arr[Symbol.iterator]();iter.next() // { value: '1', done: false }
iter.next() // { value: '2', done: false }
iter.next() // { value: '3', done: false }
iter.next() // { value: undefined, done: true }/* let [a,b,c] = arr; 所以說解構賦值就是 */let iter = arr[Symbol.iterator]();
let a = iter.next().value;
let b = iter.next().value;
let c = iter.next().value;
利用這一點我們可以這樣寫?
let [a, b] = {a: 1,b: 2,[Symbol.iterator]() {var arr = Object.values(this);return arr[Symbol.iterator]()}}
優化?
Object.prototype[Symbol.iterator] = function() {var arr = Object.values(this);return arr[Symbol.iterator]()}let [a, b] = {a: 1,b: 2}
?
那么在這個基礎上,我們在完成下面這個題,如果讓 a 使用for...of...打印出a.data里的值
let a = {data: [1,2,3,4,5,6]}for(let k of a){// 打印 1,2,3,4,5,6}
let a = {data: [1, 2, 3, 4, 5, 6]}a[Symbol.iterator] = function() {let _this = this;let index = 0return {next() {if (index < _this.data.length) {return {value: _this.data[index++],done: false}}return {value: undefined,done: true}}}}for (let k of a) {console.log(k)}