ES6 之 解構賦值

来源:https://www.cnblogs.com/evenyao/archive/2018/09/22/9689890.html
-Advertisement-
Play Games

本博文配合 阮一峰 《ES6 標準入門(第3版)》一書進行簡要概述 ES6 中變數的解構賦值。 數組的解構賦值 基本用法 ES6 允許按照一定模式,從數組和對象中提取值,對變數進行賦值,這被稱為解構。 ES6 以前,為變數賦值,只能直接指定值。 ES6 允許寫成下麵的樣式。 該代碼表示,可以從數組中 ...


本博文配合 阮一峰 《ES6 標準入門(第3版)》一書進行簡要概述 ES6 中變數的解構賦值。 

 

數組的解構賦值

基本用法

ES6 允許按照一定模式,從數組和對象中提取值,對變數進行賦值,這被稱為解構。

ES6 以前,為變數賦值,只能直接指定值。

let a = 1
let b = 2
let c = 3

 


ES6 允許寫成下麵的樣式。

let [a, b, c] = [1, 2, 3]

 

該代碼表示,可以從數組中提取值,按照對應位置,對變數賦值。

相關示例

本質上來說,這種寫法屬於“模式匹配”。即只要等號兩邊的模式相同,左邊的變數就會被賦予對應的值。下麵是一些使用嵌套數組進行解構的例子。

let [foo, [[bar], baz]] = [1, [[2], 3]]
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"]
third // "baz"

let [x, , y] = [1, 2, 3]
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4]
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a']
x // "a"
y // undefined
z // []

 


如果解構不成功,變數的值就等於 undefined

let [foo] = []
foo //undefined
let [bar, foo] = [1]
foo //undefined

 

以上兩種情況都屬於解構不成功,foo 的值都會等於undefined


另一種情況是不完全解構,即等號左邊的模式,只匹配一部分的等號右邊的數組。這種情況下,解構依然可以成功。

let [x, y] = [1, 2, 3]
x // 1
y // 2

let [a, [b], d] = [1, [2, 3], 4]
a // 1
b // 2
d // 4

 

以上兩個例子,都屬於不完全解構,但是可以成功。


如果等號的右邊不是數組(或者嚴格地說,不是可遍歷的結構),那麼將會報錯。

// 報錯
let [foo] = 1
let [foo] = false
let [foo] = NaN
let [foo] = undefined
let [foo] = null
let [foo] = {}

 

預設值

解構賦值允許指定預設值。

let [foo = true] = []
foo // true

let [x, y = 'b'] = ['a']  // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]  // x='a', y='b'



查看數組對應對值有沒有?如果沒有(數組對沒有指 undefined)就使用預設值,如果有就使用對應值。需要註意的是 undefined 和 null 的區別,一個是沒有聲明值,一個是值為 null

let [a = 2, b = 3] = [undefined, null]
a //2
b //null

ES6 內部使用嚴格相等運算符(===),判斷一個位置是否有值。所以,只有當一個數組成員嚴格等於 undefined,預設值才會生效。如果一個數組成員是 null,預設值就不會生效,因為 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 還沒有聲明。

對象的解構賦值

解構還可以用於對象。

let { foo, bar } = { foo: "aaa", bar: "bbb" }
foo // "aaa"
bar // "bbb"

由於 ES6 中對象鍵值對相同時可以略寫成一個,所以上面的代碼等同於:

let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" }
foo // "aaa"
bar // "bbb"

也就是說,對象的解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變數。真正被賦值的是後者,而不是前者。



對象的解構與數組有一個重要的不同。數組的元素是按次序排列的,變數的取值由它的位置決定;而對象的屬性沒有次序,變數必須與屬性同名,才能取到正確的值。

let { bar, foo } = { foo: "aaa", bar: "bbb" }
foo // "aaa"
bar // "bbb"

let { baz } = { foo: "aaa", bar: "bbb" }
baz // undefined

上面代碼的第一個例子,等號左邊的兩個變數的次序,與等號右邊兩個同名屬性的次序不一致,但是對取值完全沒有影響。第二個例子的變數沒有對應的同名屬性,導致取不到值,最後等於 undefined

預設值

對象的解構也可以指定預設值。

var {x = 3} = {}
x // 3

var {x, y = 5} = {x: 1}
x // 1
y // 5

var {x: y = 3} = {}
y // 3

var {x: y = 3} = {x: 5}
y // 5

var { message: msg = 'Something went wrong' } = {}
msg // "Something went wrong"

預設值生效的條件是,對象的屬性值嚴格等於undefined

 

var {x = 3} = {x: undefined}
x // 3

var {x = 3} = {x: null}
x // null

上面代碼中,屬性 x 等於 null ,因為 null 與 undefined 不嚴格相等,所以是個有效的賦值,導致預設值3不會生效。即如果解構失敗,變數的值等於undefined


如果要將一個已經聲明的變數用於解構賦值,必須非常小心。

// 錯誤的寫法
let x
{x} = {x: 1}
// SyntaxError: syntax error

上面代碼的寫法會報錯,因為 JavaScript 引擎會將{x}理解成一個代碼塊,從而發生語法錯誤。只有不將大括弧寫在行首,避免 JavaScript 將其解釋為代碼塊,才能解決這個問題。

// 正確的寫法
let x
({x} = {x: 1})

 

字元串的解構賦值

字元串也可以解構賦值。這是因為此時,字元串被轉換成了一個類似數組的對象。

const [a, b, c, d, e] = 'hello'
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"



類似數組的對象都有一個 length 屬性,因此還可以對這個屬性解構賦值。

let {length : len} = 'hello'
len // 5
 

數值和布爾值的解構賦值

解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象。

let {toString: s} = 123
s === Number.prototype.toString // true

let {toString: s} = true
s === Boolean.prototype.toString // true

上面代碼中,數值和布爾值的包裝對象都有 toString 屬性,因此變數 s 都能取到值。

解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉為對象。由於 undefined 和 null 無法轉為對象,所以直接對它們進行解構賦值,都會報錯。

let { prop: x } = undefined  // TypeError
let { prop: y } = null  // TypeError

 

函數參數的解構賦值

函數的參數也可以使用解構賦值。

function add([x, y]){
  return x + y
}

add([1, 2])  // 3

上面代碼中,函數 add 的參數錶面上是一個數組,但在傳入參數的那一刻,數組參數就被解構成變數 x 和 y 。對於函數內部的代碼來說,它們能感受到的參數就是 x 和 y

另一個例子

[[1, 2], [3, 4]].map(([a, b]) => a + b)
// [ 3, 7 ]

 

預設值

函數參數的解構也可以使用預設值。

function move({x = 0, y = 0} = {}) {
  return [x, y]
}

move({x: 3, y: 8})  // [3, 8]
move({x: 3})  // [3, 0]
move({})  // [0, 0]
move()  // [0, 0]

上面代碼中,函數 move 的參數是一個對象,通過對這個對象進行解構,得到變數 x 和 y 的值。如果解構失敗, x 和 y 等於預設值。

解構賦值的作用

變數的解構賦值用途很多。

交換變數的值

交換變數 x 和 y 的值,這樣的寫法不僅簡潔,而且易讀,語義非常清晰。

let x = 1
let y = 2

[x, y] = [y, x]

 

函數參數的定義

解構賦值可以方便地將一組參數與變數名對應起來。

// 參數是一組有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3])

// 參數是一組無次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1})

 

提取 JSON 數據

解構賦值對提取 JSON 對象中的數據,尤其有用。可以快速提取 JSON 數據的值。

let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
}

let { id, status, data: number } = jsonData

console.log(id, status, number)
// 42, "OK", [867, 5309]

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我的圖片上傳使用form表單,html: css js 後臺把數據傳給資料庫,成功後跳轉頁面,在html頁面中用這個<img src="${sessionScope.imgurl}"/> ...
  • 在 webpack.dev.config.js中 在請求金封裝的介面中 ...
  • Java中線程調用出了線程池外可以使用多個繼承於queue的類獲得多Java線程。 由於Java中所有都是對象的設定可以使用類來存儲各種數據(類似c++中的struct) 在servlet編程中,繼承自HTTPservlet類時新手推薦只重載doGet()以及doPost()函數 上個例子 其中創建 ...
  • //for in 不可以獲取不可枚舉的屬性 //hasOwnProperty 會忽略原型鏈上的屬性 //Object.getOwnPropertyNames 可以獲取可枚舉和不可枚舉的屬性 //深拷貝 ...
  • 1.靜態頁面的搭建 1 <body> 2 <div class="wrap" id="wrap"> 3 <div id="wrap_bg"> 4 <ul> 5 <li><img src="image/img_bg/img_bg_5.jpg"></img></li> 6 <li><img src="i ...
  • 高度坍塌情況: 當父元素沒有設置高度,且子元素塊都向左(右)浮動起來,那麼父元素就會出現坍塌的現象。 解決辦法: 在父元素包含塊中加一個div: 優點:相容性強,適合初學者。 缺點:不利於優化。 方法二:overflow+room 優點:相容性強。 缺點:對margin屬性有影響,不能設負值,設負值 ...
  • 具體效果圖如下: 主要用到的技術除了3D翻轉和定位 ,還用到了一個新的屬性 backface-visibility:visable|hidden; 該屬性主要是用來設定元素背面是否可見。 具體的步驟如下: 1、寫出頁面主體, 2、通過定位使兩張圖片疊加在一起 3、設置第一張圖片背面不可見 4、添加旋 ...
  • 問題描述: 在 iOS 系統中,用微信打開了 A 頁面的鏈接,然後由 A 頁面進入 B 頁面 在 B 頁面打開微信右上角菜單,使用“複製鏈接”功能 最後粘貼出來的鏈接是 A 頁面的鏈接 分析原因: 這個問題在微信 6.2 時代就已存在,GitHub 上有很多人到 weui 的主頁提 issue ht ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...