【譯】JS解構的五種有趣用法

原文標題:5 Interesting Uses of JavaScript Destructuringjavascript

原文連接:dmitripavlutin.com/5-interesti…java

按期回顧我寫的JS代碼,我發現解構運算無處不在。 獲取對象的屬性和訪問數組內容是都是很經常使用的操做。而解構運算使得這些操做變得很是簡單明瞭。 在這篇文章中,我將會講解JS解構不一樣於常見用法的五種使用技巧。數組

1. 交換變量

常見的交互兩個變量值的方法都須要藉助一個額外的變量,看一個簡單的例子:bash

let a = 1;
let b = 2;
let temp;
temp = a;
a = b;
b = temp;
a;    // => 2
b;    // => 1
複製代碼

temp是一個臨時變量,在例子中存儲了變量a的值,b的值賦給了a,最後把temp的值賦給了b。 解構運算使得交換變量的值變得很是簡單,不須要藉助第三個臨時變量:函數

let a = 1;
let b = 2;
[a, b] = [b, a];
a;    // => 2
b;    // => 1
複製代碼

[a, b] = [b, a]是一個解構運算。在等號的右側,建立了一個數組[b, a],對應的值爲[2, 1]。數組的第一個值2被解構賦值給了a,第二項1被解構賦值給了b。 即便這種方式仍然建立了一個臨時數組,可是解構賦值對於交換變量的值仍然是很是高效簡單的方式。 這種方式並無什麼限制。你還能夠同時交互更多的變量值,好比:ui

let zero = 2;
let one = 1;
let two = 0;
[zero, one, two] = [two, one, zero];
zero;    //=> 0
one;    //=> 1
two;    //=> 2
複製代碼

你能夠交換任意數量的變量值,只是兩個變量值的交換的狀況更加常見。this

2. 訪問數組

有一個數組,這個數組有多是空的。有一種需求是訪問任意位置數組元素,若是這個位置爲空,則返回一個默認值。 一般狀況下有的人可能會使用數組的length屬性作判斷:spa

const colors = [];
let firstColor = "white";
if (colors.length > 0) {
    firstColor = colors[0];
}
firstColor;    //=> "white"
複製代碼

幸運的是,數組解構能夠更快捷高效的實現相同的效果:rest

const colors = [];
const [firstColor = "white"] = colors;
firstColor;    //=> "white"
複製代碼

const [firstColor = "white"] = colors;colors數組的第一個元素賦值給了變量firstColor。若是這個數組的下標爲0的位置上沒有任何元素(注:爲undefined時即認爲爲空),white將做爲默認值賦值給firstColor。 數組解構是很是靈活的,若是你只想訪問數組的第二個元素,方法以下所示:code

const colors = [];
const [, secondColor = "black"] = colors;
secondColor;    //=> "black"
複製代碼

在解構表達式的左邊寫一個逗號:意味着數組的第一個元素被忽略掉。colors數組下標爲1的元素被解構賦值給了變量secondColor

3. 不可變操做

從我開始使用React,到後來的Redux,我被迫開始寫一些遵循不可變原則的代碼。剛開始的時候確實有點不適應,不事後來我就意識到了這種方式的好處:它使得處理單向數據流更加容易。 不可變原則禁止修改對象。幸運的是,解構能夠幫助你在遵循不可變原則的同時完成這些操做。 將解構與展開運算符(rest operator)結合使用來移除數組的第一個元素:

const numbers = [1,2,3];
const [, ...fooNumbers] = numbers;
fooNumbers;    //=> [2, 3]
numbers;    //=> [1,2,3]
複製代碼

這個解構操做[, ...fooNumbers] = numbers建立了一個新的數組fooNumbers,這個數組包含numbers除了第一個元素外的其他元素。 numbers數組並無被改變,這種方式遵循了不可變原則。 除此以外,你也能夠在遵循不可變原則的同時使用一樣的方法來刪除一個對象的屬性。以下所示,刪除big對象的foo屬性:

const big = {
    foo: "value foo",
    bar: "value bar",
}
const { foo, ...small } = big;
small;    //=> { bar: "value bar" }
big;    //=>{ foo: "value foo", bar: "value bar" }
複製代碼

上述方法將解構與對象展開運算符結合起來使用,建立了一個新的對象small,這個新對象包含big對象除了foo屬性以外的全部屬性。

4. 解構可迭代的值

在前面幾部份內容中,都是解構的數組。實際上解構運算是能夠用於全部的可迭代對象的。 許多原生的基礎類型和對象都是可迭代的,例如數組,類數組,字符串,set集合和map集合。 例如,你能夠把字符串解構成單個字符:

const str = "cheese";
const [firstChar = ""] = str;
firstChar;    //=> 'c'
複製代碼

固然解構不單單限於原生可迭代的那幾種類型。解構能夠被用於全部實現了迭代接口(iterable protocol)的對象。 以下所示,movies包含一個movie對象列表。咱們想要解構movies對象的時候,能夠獲取到電影的title這個字符串。實現這個操做首先須要自定義一個迭代器:

const movies = {
    list: [
        { title: "Heat" },
        { title: "Interstellar" },
    ],
    [Symbol.iterator]() {
        let index = 0;
        return {
            next: () => {
                if (index < this.list.length) {
                    const value = this.list[index++].title;
                    return { value, done: false };
                }
                return { done: true }
            }
        }
    }
}

const [firstMovieTitle] = movies;
console.log(firstMovieTitle); //=> 'Heat'
複製代碼

movies對象經過定義Symbol.iterator方法實現了一個迭代器。這個迭代器能夠迭代全部電影的title屬性。 咱們在movies對象上遵循了迭代接口實現,從而實現了經過解構movies來獲取到標題,好比咱們獲取第一個電影的標題:const [firstMovieTitle] = movies;。 解構用法的上限就是沒有上限。

5. 解構動態屬性

在個人經驗中,解構一個對象的屬性要遠比解構一個數組的狀況更多。 解構對象看起來很是的簡單:

const movie = { title: "Heat" };
const { title } = movie;
title;    //=> Heat
複製代碼

const { title } = movie;建立了一個變量title,而後把movie.title的值賦值給了這個變量。 當我第一次瞭解到對象解構的時候,有一點令我驚訝的是你並不須要預先知道屬性的靜態名稱。你能夠經過動態屬性名來解構一個對象。 爲了瞭解動態解構的工做原理,咱們來寫一個打招呼的函數做爲例子:

function greet( obj, nameProp ) {
    const { [nameProp]: name="Unknow" } = obj;
    return `Hello, ${name}!`;
}
greet({ name: "Batman" }, "name");    //=>    Hello, Batman!
greet( {}, "name" );    //=>    Hello, Unknow!
複製代碼

greet()被調用時須要傳遞兩個參數,一個是對象,一個是屬性名稱。 在greet()函數內部,解構表達式const { [nameProp]: name="Unknow" } = obj;使用中括號[nameProp]讀取動態屬性的名稱。name變量接收動態屬性的值。 更好的作法就是你能夠指定一個默認的值Unknow以防屬性不存在的狀況。

6. 總結

解構能夠幫助你更方便快捷的訪問對象屬性和數組元素。 除了基本用法以外,數組解構還能夠方便的交換變量,訪問數組元素,作一些遵循不可變原則的操做。 JavaScript提供了更多的可能性,由於你能夠經過擴展迭代器實現自定義的解構邏輯。

相關文章
相關標籤/搜索