深入理解ES6 005【學習筆記】

解構:使用資料存取更便捷

如果使用 var、let 或 const 解構宣告變數,則必須提供初始化程式(也就是等號右側的值),如下會導致錯誤

// 語法錯誤
var {tyep,name}

// 語法錯誤
let {type,name}

// 語法錯誤
const {type,name}

使用解構給已經宣告的變數賦值,如下

let node = {
  type:"Identifier",
  name:"foo"
},
type = "Literal",
name = 5;

// 使用解構語法為多個變數賦值 ,請注意一定要使用小括號包裹解構賦值的方法(js引擎將一對開放的花括號視為一個程式碼區塊,而語法規定,程式碼區塊語句不允許出現在賦值語句側,添加小括號後可以將語句轉化為一個運算式
({type,name}=node)
console.log(type) // Identifier
console.log(name) // foo

解構賦值運算式的值與運算式右側(也就是 = 右側)的值相等,如此一來,在任何可以使用值的地方你都可以使用解構賦值運算式,如下:

let node = {
  type:"Identifier",
  name:"foo"
},
type = "Literal",
name = 5;

function outputinfo(value){
  console.log(value===node); // true
}

outputinfo({type,name} = node);

console.log(type) // "Identifier"
console.log(name) // "foo"
// 運算式的值為右側的值,這個寫法是value傳的是node,並給type和name進行了賦值
// 呼叫outputInfo()函式時傳入了一個解構運算式,由於javascript運算式的值為右側的值,因此此處傳入的參數等同於node,且變數type和name被重新賦值,最終將node傳入outputInfo()函式

解構賦值運算式(也就是 = 右側的運算式)如果為 null 或 undefined 會導致程式拋出錯誤。任何嘗試讀取nullundefined的屬性行為都會觸發執行時錯誤。

預設值

使用解構賦值運算式時,如果指定的區域變數名稱在物件中不存在,那麼這個區域變數會被賦值為undefined

let node = {
  type:"Identifier",
  name:"foo"
}
let {type,name,value} = node;
console.log(type) //Identifier
console.log(name) // foo
console.log(value) // undefined

// 預設值 當指定屬性不存在時,可以隨意定義一個預設值,在屬性名稱後添加一個等號(=)和相應的預設值即可

let node = {
  type:"Identifier",
  name:"foo"
}
let {type,name,value=true} = node; // 只有當node上沒有該屬性或者該屬性值為undefined時該值才生效
console.log(type) //Identifier
console.log(name) // foo
console.log(value) // true

非同名區域變數賦值

解構賦值使用的都是與物件屬性同名的區域變數,例如,node.type 的值被儲存在變數 type 中。但如果你希望使用不同命名的區域變數來儲存物件屬性的值,

let node = {
  type:"Identifier",
  name:"foo"
}
let {type:localType,name:localName="bar"} = node;
console.log(type) //Identifier
console.log(name) // foo

// 不同名本地變數,並使用預設值
let node = {
  type:"Identifier"
}
let {type:localType,name:localName="bar"} = node;
console.log(type) //Identifier
console.log(name) // bar

巢狀物件解構

解構巢狀物件仍然與物件字面量的語法相似,可以將物件拆解以獲取你想要的資訊

let node = {
  type:"Identifier",
  name:"foo",
  loc:{
    start:{
      line:1,
      column:1
    },
    end:{
      line:1,
      column:4
    }
  }
}
let {loc:{start}} = node;
console.log(start.line); // 1
console.log(start.column); // 1

// 使用不同的名的本地變數來
let node = {
  type:"Identifier",
  name:"foo",
  loc:{
    start:{
      line:1,
      column:1
    },
    end:{
      line:1,
      column:4
    }
  }
}
let {loc:{start:localStart}} = node;
console.log(localStart.line); // 1
console.log(localStart.column); // 1

下面這條語句,由於右側只有一對花括號,因而其不會宣告任何繫結,loc 不是即將建立的繫結,它代表了在物件中檢索屬性的位置。

// 未宣告任何變數!
let {loc:{}} = node

陣列解構

與物件解構的語法相比,陣列解構就簡單多了,它使用的是陣列字面量,且解構操作全部在陣列內完成,而不是像物件字面量語法一樣使用物件

let colors = ["red","green","blue"]
let [firstColor,secondColor]=colors
console.log(firstColor) //red
console.log(firstColor) // green
// 只為感興趣的元素提供變數,切記,在這個過程中,陣列本身不會發生任何變化
let [,,thirdColor] = colors;
console.log(thirdColor) // blue

陣列解構賦值

陣列解構賦值上下文,但不需要用小括號包裹運算式。

有關陣列解構賦值的這些語法已經足夠使用了,陣列解構語法還有一個獨特的用例:變數交換的應用

如果右側陣列解構賦值運算式為 null 或 undefined,則會導致程式拋出錯誤,這一特性與物件解構值很相似

let a = 1, b = 2;
[a,b] = [b,a];
console.log(a)  // 2
console.log(b)  // 1

巢狀陣列解構

let colors = ["red",["green","lightgreen"],"blue"];
// 
let [firstColor,[secondColor]] = colors;
console.log(firstColor); // red
console.log(secondColor); // green

不定元素

可以透過...語法將陣列中的其餘元素賦值給一個特定的變數,

let colors = ["red","green","blue"]
let [firstColor,...restColors] = colors;
console.log(firstColor) // "red"
console.log(restColors[0]); // green
console.log(restColors[1]); // blue

ES5 經常使用concat()方法來複製(clone)陣列,如果呼叫時不傳遞參數就會返回當前函式的副本。ES6 可以透過不定元素的語法來實現相同的目標

// es5
var colors = ["red","green","blue"];
var clonedColors = colors.concat();
console.log(clonedColors) // [red,green,blue]
// es6
let colors = ["red","green","blue"];
let [...clonedColors] = colors;
console.log(clonedColors); // [red,green,blue]

在被解構的陣列中,不定元素必須為最後一個條目,在後面繼續添加逗號會導致程式拋出語法錯誤,可以使用物件解構來建立更多複雜的運算式,如此一來,可以從任何混雜著物件和陣列的資料解構中提取你想要的資訊

let node = {
  type: "Identifier",
  name: "foo",
  loc: {
    start: {
      line: 1,
      column: 4
    },
    end: {
      line: 1,
      column: 4
    }
  },
  range: [0,3]
}

let {
  loc:{start},
  range:[startIndex]
}
console.log(start.line); // 1
console.log(start.column); // 1
console.log(startIndex); 0

解構參數

當定義一個接受大量可選參數的 JavaScript 函式時,我們通常會建立一個可選物件,將額外的參數定義為這個物件屬性

  • 必須傳值的解構參數
  • 解構參數的預設值
function setCookie(name,value,{
  source = false,
  path = '/',
  domain = 'example.com',
  expires = new Date(Date.now()+360000*1000)
}){
  // 設定cookie的程式碼
}

setCookie("type","js",{secure:true,expires:60000})
// 解構參數有一個奇怪的地方,預設情況下,如果呼叫函式時不提供被解構的參數會導致程式拋出錯誤。如下,如果不傳遞第3個參數,會報錯
// 程式報錯!
setCookie("type","js");
// 缺失第3個參數,其值為undefined,而解構參數只是將解構宣告應用在函式參數的一個簡寫方法,即如果解構賦值運算式右值為null或undefined,則程式會報錯,同理,若呼叫setCookie()函式不傳入第3個參數,也會導致程式拋出錯誤
// 好的做法是為其提供相同的預設值
const setCookieDefaults = {
  secure:false,
  path: "/",
  domain: "example.com",
  expires: new Date(Date.now()+360000000)
}
function setCookie(name,value,{
   secure:false,
  path: "/",
  domain: "example.com",
  expires: new Date(Date.now()+360000000)
}=setCookieDefaults) {
  // ....
}

在物件和陣列解構中,都可以為值為 undefined 的物件屬性或陣列元素設定預設值,且賦值運算式右值不可為 null 或 undefined,否則程式會拋出錯誤。可以使用varletconst來解構宣告變數,但按照語法規定必須要指定相應的初始化程式。

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4331

(0)
Walker的頭像Walker
上一篇 2025年3月8日 12:51
下一篇 2025年3月8日 12:39

相關推薦

  • 深入理解ES6 001【學習筆記】

    區塊作用域繫結 之前的變數宣告 `var` 無論在哪裡宣告,都會被視為作用域頂部宣告。由於函式是一等公民,因此順序通常是 `function 函式名稱()`、`var 變數`。 區塊宣告 區塊宣告用於宣告在指定區塊的作用域之外無法存取的變數。區塊作用域存在於: 函式內部 區塊中(字元 `{` 和 `}` 之間的區域) 暫時性死區 JavaScript 引擎在掃描程式碼發現變數宣告時,要麼會將它們提升至作…

    個人 2025年3月8日
    1.6K00
  • 從0到1落地微前端架構 001【學習筆記】

    微前端 js 隔離css 隔離元素隔離生命週期預載入資料通訊應用程式跳轉多層巢狀 說明 使用的是 Mermaid 的 flowchart 語法,Markdown 渲染器如 Typora、VitePress、一些 Git 平台都支援。 保留了: 基座應用 main-vue3 各子應用:child-nuxt2-home、child-vue2-job、child-vu…

    2025年4月20日
    1.5K00
  • Go工程師體系課 protobuf_guide【學習筆記】

    Protocol Buffers 入門指南 1. 簡介 Protocol Buffers(簡稱 protobuf)是 Google 開發的一種語言無關、平台無關、可擴充的結構化資料序列化機制。與 JSON、XML 等序列化方式相比,protobuf 更小、更快、更簡單。 專案首頁:https://github.com/protocolbuffers/prot…

    個人 2025年11月25日
    1.2K00
  • 深入理解ES6 011【學習筆記】

    Promise與異步程式設計 因為執行引擎是單執行緒的,所以需要追蹤即將執行的程式碼,那些程式碼會被放在一個任務佇列中,每當一段程式碼準備執行時,都會被新增到任務佇列中,每當引擎中的一段程式碼結束執行時,事件迴圈會執行佇列中的下一個任務。 Promise 相當於異步操作結果的佔位符,它不會去訂閱一個事件,也不會傳遞一個回呼函式給目標函式,而是讓函式回傳一個 Promise,就像這樣…

    個人 2025年3月8日
    1.1K00
  • 深入理解ES6 008【學習筆記】

    迭代器(Iterator)和產生器(Generator)這項新特性對於高效的資料處理而言是不可或缺的,你也會發現在語言的其他特性中也都有迭代器的蹤影:新的 for-of 迴圈、展開運算子 (...)、甚至連非同步程式設計都可以使用迭代器。 迭代器是一種特殊的物件,它具有一些專門為迭代過程設計的專有介面,所有的迭代器物件都有一個 next() 方法,每次呼叫都傳回一個結果對…

    個人 2025年3月8日
    1.1K00
簡體中文 繁體中文 English
歡迎🌹 Coding never stops, keep learning! 💡💻 光臨🌹