摘要:基本原理解構是提供的語法糖,其實內在是針對可迭代對象的接口,通過遍歷器按順序獲取對應的值進行賦值。屬性值返回一個對象的無參函數,被返回對象符合迭代器協議。迭代器協議定義了標準的方式來產生一個有限或無限序列值。
更多系列文章請看1、基本語法 1.1、數組
// 基礎類型解構 let [a, b, c] = [1, 2, 3] console.log(a, b, c) // 1, 2, 3 // 對象數組解構 let [a, b, c] = [{name: "1"}, {name: "2"}, {name: "3"}] console.log(a, b, c) // {name: "1"}, {name: "2"}, {name: "3"} // ...解構 let [head, ...tail] = [1, 2, 3, 4] console.log(head, tail) // 1, [2, 3, 4] // 嵌套解構 let [a, [b], d] = [1, [2, 3], 4] console.log(a, b, d) // 1, 2, 4 // 解構不成功為undefined let [a, b, c] = [1] console.log(a, b, c) // 1, undefined, undefined // 解構默認賦值 let [x = 1] = [undefined];// x=1; let [x = 1] = [null];// x=null; // 數組成員嚴格等于undefined,默認值才會生效 let [x = 1, y = x] = []; // x=1; y=1 let [x = 1, y = x] = [2]; // x=2; y=2 let [x = 1, y = x] = [1, 2]; // x=1; y=2 let [x = y, y = 1] = []; // ReferenceError: y is not defined 因為x用y做默認值時,y還沒有聲明1.2 對象
// 對象屬性解構 let { f1, f2 } = { f1: "test1", f2: "test2" } console.log(f1, f2) // test1, test2 // 可以不按照順序,這是數組解構和對象解構的區別之一 let { f2, f1 } = { f1: "test1", f2: "test2" } console.log(f1, f2) // test1, test2 // 解構對象重命名 let { f1: rename, f2 } = { f1: "test1", f2: "test2" } console.log(rename, f2) // test1, test2 // 嵌套解構 let { f1: {f11}} = { f1: { f11: "test11", f12: "test12" } } console.log(f11) // test11 // 默認值 let { f1 = "test1", f2: rename = "test2" } = { f1: "current1", f2: "current2"} console.log(f1, rename) // current1, current21.3 字符串/數值/布爾值
// String let [ a, b, c, ...rest ] = "test123" console.log(a, b, c, rest) // t, e, s, [ "t", "1", "2", "3" ] let {length : len} = "hello"; // en // 5 // number let {toString: s} = 123; s === Number.prototype.toString // true // boolean let {toString: s} = true; s === Boolean.prototype.toString // true // Map let [a, b] = new Map().set("f1", "test1").set("f2", "test2") console.log(a, b) // [ "f1", "test1" ], [ "f2", "test2" ] // Set let [a, b] = new Set([1, 2, 3]) console.log(a, b) // 1, 22、使用場景 2.1、 淺拷貝
let colors = [ "red", "green", "blue" ]; let [ ...clonedColors ] = colors; console.log(clonedColors); // "[red,green,blue]"
注意這里是淺拷貝2.2、 交換變量
let x = 1; let y = 2; [x, y] = [y, x];2.3、遍歷Map結構
var map = new Map(); map.set("first", "hello"); map.set("second", "world"); for (let [key, value] of map) { console.log(key + " is " + value); }2.4、函數參數
function add(a,b,{c,d}){ // ... } add(1,2,{}); add(1,2)//Uncaught TypeError: Cannot destructure property `c` of "undefined" or "null"
解構賦值的規則是,若等號右邊的值不是對象或者數組,就會先將其轉化成對象。由于undefined和null無法轉化成對象,所以對其進行解構賦值時會報錯。
它實際上是這樣運行的:
function add(a, b, options) { let { c,d } = options; // ... }
由于add(1,2)沒有傳options導致異常,如果我們options是選填的那么可以像下面這樣
function add(a,b,{c,d}={}){ // ... }
當然大部分情況我們可以給默認值
function move ({x:0,y:0}={}){} move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, 0] move({}); // [0, 0] move(); // [0, 0]
function move ({x,y}={x:0,y:0}){} move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, undefined] move({}); // [undefined, undefined] move(); // [0, 0]
上面代碼是為函數move的參數指定默認值,而不是為變量x和y指定默認值,所以會得到與前一種寫法不同的結果。
undefined就會觸發函數參數的默認值。
[1, undefined, 3].map((x = "yes") => x);3、基本原理
解構是ES6提供的語法糖,其實內在是針對可迭代對象的Iterator接口,通過遍歷器按順序獲取對應的值進行賦值。這里需要提前懂得ES6的兩個概念:
Iterator
可迭代對象
3.1、Iterator概念Iterator是一種接口,為各種不一樣的數據解構提供統一的訪問機制。任何數據解構只要有Iterator接口,就能通過遍歷操作,依次按順序處理數據結構內所有成員。ES6中的for of的語法相當于遍歷器,會在遍歷數據結構時,自動尋找Iterator接口。
Iterator作用:
為各種數據解構提供統一的訪問接口
使得數據解構能按次序排列處理
可以使用ES6最新命令 for of進行遍歷
function makeIterator(array) { var nextIndex = 0 return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++]} : {done: true} } }; } var it = makeIterator([0, 1, 2]) console.log(it.next().value) // 0 console.log(it.next().value) // 1 console.log(it.next().value) // 23.2、可迭代對象
可迭代對象是Iterator接口的實現。這是ECMAScript 2015的補充,它不是內置或語法,而僅僅是協議。任何遵循該協議點對象都能成為可迭代對象。可迭代對象得有兩個協議:可迭代協議和迭代器協議。
可迭代協議:對象必須實現@@iterator方法。即對象或其原型鏈上必須有一個名叫Symbol.iterator的屬性。該屬性的值為無參函數,函數返回迭代器協議。
屬性 | 值 |
---|---|
Symbol.iterator | 返回一個對象的無參函數,被返回對象符合迭代器協議。 |
迭代器協議:定義了標準的方式來產生一個有限或無限序列值。其要求必須實現一個next()方法,該方法返回對象有done(boolean)和value屬性。
屬性 | 值 |
---|---|
next | 返回一個對象的無參函數,被返回對象擁有兩個屬性:done和value done :如果迭代器已經經過了被迭代序列時為 true。這時 value 可能描述了該迭代器的返回值。如果迭代器可以產生序列中的下一個值,則為 false。這等效于連同 done 屬性也不指定。 value :迭代器返回的任何 JavaScript 值。done 為 true 時可省略。 |
通過以上可知,自定義數據結構,只要擁有Iterator接口,并將其部署到自己的Symbol.iterator屬性上,就可以成為可迭代對象,能被for of循環遍歷。
3.3、解構語法糖String、Array、Map、Set等原生數據結構都是可迭代對象,可以通過for of循環遍歷它。故可以通過ES6解構語法糖依次獲取對應的值。
// String let str = "test" let iterFun = str[Symbol.iterator] let iterator = str[Symbol.iterator]() let first = iterator.next() // 等效于 let [first] = "test" console.log(iterFun, iterator, first) // 打印 // [Function: [Symbol.iterator]], {}, { value: "t", done: false } // Array let arr = ["a", "b", "c"]; let iter = arr[Symbol.iterator](); // 以下等效于 let [first, second, third, four] = ["a", "b", "c"] let first = iter.next() // { value: "a", done: false } let second = iter.next() // { value: "b", done: false } let third = iter.next() // { value: "c", done: false } let four = iter.next() // { value: undefined, done: true }4、性能
當我們有解構賦值的形式來做函數參數時,執行的時候會增加很多中間變量,內存也會比之前高。但是業務代碼還是更加關注可讀性和可維護性。如果你寫的是庫代碼,可以嘗試這種優化,把參數展開后直接傳遞,到底能帶來多少性能收益還得看最終的基準測試。
參考ES6 的解構賦值前每次都創建一個對象嗎?會加重 GC 的負擔嗎?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102895.html
摘要:它是一個通用標準,奠定了的基本語法。年月發布了的第一個版本,正式名稱就是標準簡稱。結語的基本擴展還有一些沒有在這里詳細介紹。 前言 ES6標準以及頒布兩年了,但是,好像還沒有完全走進我們的日常開發。這篇文章從ES6的基本類型擴展入手,逐步展開對ES6的介紹。 ECMAScript和JavaScript JavaScript是由Netscape創造的,該公司1996年11月將JavaSc...
摘要:沒有箭頭函數沒有自己的對象,這不一定是件壞事,因為箭頭函數可以訪問外圍函數的對象那如果我們就是要訪問箭頭函數的參數呢你可以通過命名參數或者參數的形式訪問參數不能通過關鍵字調用函數有兩個內部方法和。 1、基本語法回顧 我們先來回顧下箭頭函數的基本語法。ES6 增加了箭頭函數: var f = v => v; // 等同于 var f = function (v) { return ...
摘要:如果變量名與屬性名不一致,必須寫成下面這樣。這是因為此時,字符串被轉換成了一個類似數組的對象。數字和布爾的解構賦值,解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象。參數也可以是無序的解構賦值對提取對象中的數據,可以快速提取 ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構ES6之前我們申明多個變量需要按照下面的方法: let a=1; let b=2...
摘要:如果變量名與屬性名不一致,必須寫成下面這樣。這是因為此時,字符串被轉換成了一個類似數組的對象。數字和布爾的解構賦值,解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象。參數也可以是無序的解構賦值對提取對象中的數據,可以快速提取 ES6 允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構ES6之前我們申明多個變量需要按照下面的方法: let a=1; let b=2...
閱讀 2255·2023-04-26 02:14
閱讀 2926·2021-09-30 09:46
閱讀 2101·2021-09-24 09:48
閱讀 952·2021-09-24 09:47
閱讀 3252·2019-08-30 15:44
閱讀 1879·2019-08-30 15:44
閱讀 3279·2019-08-30 14:18
閱讀 1949·2019-08-30 12:58