1. 程式人生 > 程式設計 >JS ES新特性之變數的解耦賦值

JS ES新特性之變數的解耦賦值

目錄
  • 1.陣列的解耦賦值
    • 1.1陣列解耦賦值是什麼
    • 1.2陣列解耦賦值失敗
    • 1.3不完全解耦賦值
    • 1.4預設值
    • 1.5陣列解耦賦值的複雜情況
  • 2.物件的解耦賦值
    • 2.1物件解耦賦值的特殊情況
    • 2.2解耦賦值失敗
    • 2.3不完全解耦賦值
    • 2.4預設值
  • 3.字串、數值、和布林值的解耦賦值
    • 3.1字串解耦賦值
    • 3.2數值和布林值的解耦賦值
  • 4.函式的解耦賦值
    • 5.小括號的問題
      • 5.1不能使用小括號的情況
      • 5.2可以使用小括號的情況
    • 6.變數解耦賦值的用處
      • 6.1交換變數的值
      • 6.2從函式返回多個值
      • 6.3函式引數的定義
      • 6.4提取 ON 資料

    1.陣列的解耦賦值

    1.1陣列解耦賦值是什麼

    ECMAScript 2015中允許按照一定模式,從陣列和物件中提取值,對變數進行賦值,這被稱為 解耦賦值 。

    在ECMAScript 2015之前中為變數賦值的方式如下所示:

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

    在ECMAScript 2015允許寫成下面這樣。

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

    ECMAScript 2015的解耦賦值本質上屬於模式匹配。賦值運算子兩邊的模式相同,左邊的變數會被賦予對應位置的值。

    1.2陣列解耦賦值失敗

    如果解耦賦值失敗的話,變數的值等於 undefined。示例程式碼如下所示:

    // 如果陣列的某個索引值的位置的變數,在 = 運算子的右邊沒有陣列中沒有對應的索引值與之對應,則解耦賦值失敗,其值為 undefined
    let [v] = []
    letwww.cppcns.com
    [a,b] = [1] console.log(v,a,b); // undefined 1,undefined

    如果想解決解耦賦值失敗的問題,需要將其賦值運算子的左右兩邊的數量保持一致。

    1.3不完全解耦賦值

    所謂的不完全解耦賦值就是指賦值運算子的右邊陣列中的數量要大於左邊陣列中的數量,導致右邊陣列中的有些變數失效,但是這這種情況下解耦賦值還是會成功的。

    示例程式碼如下所示:

    // 賦值運算子左邊變數的數量小於右邊值的數量
    let [a,3,4]  // 依然會解耦賦值成功
    console.log(a,c); // 1 2 3
    
    
    

    1.4預設值

    解耦賦值允許指定預設值的。示例程式碼如下所示:

    /* 
     * 解耦賦值中允許指定預設值
     * 語法結構如下
     * let [var1 = value1,var2 = value2,...] = [val1,val2,...]
       var1,var2 表示變數名
       value1,value2 表示預設值
       val1,val2,表示指定的值
     */
    let [a = 1,b = 2] = [100]
    console.log(a,b); // 100 2
    
    
    

    在使用預設值的時候值得注意的一點就是,ECMAScript6 內部會使用全等於 === 運算子來判斷指定位置的值是否全等於undefined。只有當 全等於undefined時,其預設值才會生效。

    測試程式碼如下所示:

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

    當我們使用null值時,雖然null也表示為空,但是null !== undefined。所以我們的預設值並不會生效,

    測試程式碼如下:

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

    1.5陣列解耦賦值的複雜情況

    由於是一個弱型別的語言,所以賦值號右邊是什麼型別都是允許的,那就會出現以下幾種特殊情況:

    情況一:運算子右邊是一個函式,示例程式碼如下

    // 1. 運算子右邊是一個函式
    let [a,b] = [1,function () {
      return 10;
    }]
    console.log(b()); // 10
    
    
    

    情況二:運算子右邊是一個物件,示例程式碼如下

    // 2. 運算子右邊是一個物件
    let [a,{
      name: '狐妖小紅娘'
    }]
    console.log(b); // { name: '狐妖小紅娘' }
    
    
    

    情況三:運算子右邊函式陣列,示例程式碼如下

    // 3. 運算子右邊是含有陣列
    let [a,[2,3]]
    console.log(b); // [ 2,3 ]
    
    
    

    情況四:運算子左右兩邊都含有陣列,示例程式碼如下所示

    // 4. 運算子左右兩邊都含有陣列,示例程式碼如下所示
    let [a,[b,c]] = [1,3]]
    console.log(b); // 2
    
    
    

    2.物件的解耦賦值

    物件的解耦賦值是通過變數名稱實現與物件的屬性名稱一一對應實現的。示例程式碼如下所示:

    /*
      * 物件的解耦賦值 - 從物件中提取值,為變數賦值
        ! 變數名稱必須與物件的屬性名稱一一對應,否則就會導致失敗。
    */
    let {
      x,y
    } = {
      x: 10,y: 20
    }
    console.log(x,y); //10 20
    
    
    

    值得注意的是賦值運算子兩邊的格式需要保持一致。

    2.1物件解耦賦值的特殊情況

    由於 Script 是一個弱型別的語言,所以賦值號右邊是什麼型別都是允許的,那就會出現以下幾種特殊情http://www.cppcns.com

    情況一:運算子右邊是一個函式,示例程式碼如下

    // 1. 運算子右邊是一個函式
    let { a,b } = {
      a: 1,b: function () {
        return 10;
      }
    }
    console.log(b());// 10
    
    
    

    情況二:運算子右邊是一個物件,示例程式碼如下

    // 2. 運算子右邊是一個物件
    let {a,b} = {
      a: 1,b: {
        name: 'ywanzhou'
      }
    }
    console.log(b); // { name: 'ywanzhou' }
    
    
    

    情況三:運算子右邊函式陣列,示例程式碼如下

    // 3. 運算子右邊是含有陣列
    let {a,b: [1,2]
    }
    console.log(b); //[ 1,2 ]
    
    
    

    情況四:運算子左右兩邊都含有物件,示例程式碼如下所示

    // 4. 運算子左右兩邊都含有物件
    let {
      m: {
        name,age
      },n
    } = {
      m: {
        name: 'test',age: 20
      },n: 20
    }
    console.log(name,age); // test 20
    
    

    2.2解耦賦值失敗

    如果解耦賦值失敗的話,變數的值等於undefined。示例程式碼如下所示:

    // 解耦賦值失敗
    let {
      a,b
    } = {
      a: 10
    }
    console.log(b);
    
    
    

    2.3不完全解耦賦值

    所謂的不完全解耦賦值就是指賦值運算子的右邊物件中屬性的數量要大於左邊物件中屬性的數量,導致右邊物件中屬性的有些變數失效,但是這這種情況下解耦賦值還是會成功的。

    // 不完全解耦賦值
    let {
      a
    } = {
      a: 10,b: 20
    }
    console.log(a);
    
    
    

    2.4預設值

    解耦賦值允許指定預設值的。示例程式碼如下所示:

    // 預設值
    let {
      a,b = 100
    } = {
      a: 10,b: 20
    }
    console.log(b);
    
    
    

    3.字串、數值、和布林值的解耦賦值

    3.1字串解耦賦值

    字串也可以解構賦值。這是因為此時,字串被轉換成了一個類似陣列的物件。

    let [h1,y,x] = "一碗周"
    console.log(h1,x,h2); // 一 碗 周
    
    
    

    3.2數值和布林值的解耦賦值

    如果直接對數字值/布林值進行解耦賦值會丟擲異常,在對數字值和布林值進行操作時,其賦值運算子的右邊是數值和布林值,則會先轉為物件。

    // let [a] = 100; // 丟擲異常 描述資訊為 TypeError: 100 is not iterable
    // console.log(a);
    // 對布林或者數值進行解耦賦值的話, 需要現將其改變成為物件型別。
    let {
      toString: b
    } = 1;
    console.log(b === Number.prototype.toString); // true
    
    let {
      toString: c
    } = true;
    console.log(c === Boolean.prototype.toString); // true
    

    解構賦值的規則是,只要等號右邊的值不是物件或陣列,就先將其轉為物件。由於undefinednull無法轉為物件,所以對它們進行解構賦值,都會報錯。

    4.函式的解耦賦值

    函式的引數也可以使用解構賦值。示例程式碼如下所示:

    // 使用陣列
    function f([a,b]) {
      console.log(a,b);  
    }
    f([10,20]) // 10 20
    // 使用物件
    function fn({
      a,b
    }) {
      console.log(a,b);
    }
    fn({
      a: 10,b: 20
    })  // 10 20
    
    
    

    5.小括號的問題

    解耦賦值雖然很方便,但是解析起來並不容易。對於編譯器來說,一個式子到底是模式,還是表示式,沒有辦法從一開始就知道,必須解析到(或解析不到)等號才能知道。

    由此帶來的問題是,如果模式中出現小括號怎麼處理。ECMAScript 2015的規則是,只要有可能導致解構的歧義,就不得使用小括號。

    但是,這條規則實際上不那麼容易辨別,處理起來相當麻煩。因此,建議只要有可能,就不要在模式中放置小括號。

    5.1不能使用小括號的情況

    如下三種情況不能使用小括號

    情況一:變數宣告語句,示例程式碼如下所示

    // 如下情況全部會報錯
    let [(a)] = [1];
    
    let {x: (c)} = {};
    let ({x: c}) = {};
    let {(x: c)} = {};
    let {(x): c} = {};
    
    let { o: ({ p: p }) } = { o: { p: 2 } };
    
    

    上面6個語句都會報錯,因為它們都是變數宣告語句,模式不能使用小括號。

    情況二:作為函式引數

    函式引數也屬於變數宣告,因此不能帶有小括號。

    // 報錯
    function f([(z)]) { return z; }
    // 報錯
    function f([z,(x)]) { r客棧eturn x; }
    

    情況三:賦值語句的模式

    // 全部報錯
    ({ p: a }) = { p: 42 };
    ([a]) = [5];
    
    
    

    上面程式碼將整個模式放在小括號之中,導致報錯。

    // 報錯
    [({ p: a }),{ x: c }] = [{},{}];
    
    
    

    上面程式碼將一部分模式放在小括號之中,導致報錯。

    5.2可以使用小括號的情況

    可以使用小括號的情況只有一種:賦值語句的非模式部分,可以使用小括號。

    [(b)] = [3]; // 正確
    ({ p: (d) } = {}); // 正確
    [(parseInt.prop)] = [3]; // 正確
    
    

    上面三行語句都可以正確執行,因為首先它們都是賦值語句,而不是宣告語句;其次它們的小括號都不屬於模式的一部分。第一行語句中,模式是取陣列的第一個成員,跟小括號無關;第二行語句中,模式是p,而不是d;第三行語句與第一行語句的性質一致。

    6.變數解耦賦值的用處

    變數解耦賦值的用處有很多,下面舉幾個比較常見的例子。

    6.1交換變數的值

    如果沒有解耦賦值交換變數需要藉助第三個變數才能完成,示例程式碼如下所示:

    var a = 10,b = 20;
    
    var c = a;
    a = b
    b = c
    c = null  /// 釋放變數
    console.log(a,b); // 20 10
    
    
    

    藉助變數解耦賦值完成 ,示例程式碼如下所示:

    let a = 10,b = 20;
    [a,b] = [b,a]
    console.log(a,b); // 20 10
    
    
    

    使用這種方式不僅簡潔,而且易讀,語義清晰。

    6.2從函式返回多個值

    函式只能返回一個值,如果要返回多個值,只能將它們放在陣列或物件裡返回。有了解構賦值,取出這些值就非常方便。

    示例程式碼如下所示:

    // 返回一個數組
    
    function example() {
      return [1,3];
    }
    let [a,c] = example();
    
    // 返回一個物件
    
    function examplwww.cppcns.come() {
      return {
        foo: 1,bar: 2
      };
    }
    let { foo,bar } = example();
    
    

    6.3函式引數的定義

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

    // 引數是一組有次序的值
    function f([x,z]) {
      console.log(x,z);
    }
    f([1,3]);  // 1 2 3
    
    // 引數是一組無次序的值
    function fn({x,z}) {
      console.log(x,z);
    }
    fn({
      z: 3,y: 2,x: 1
    });  // 1 2 3
    
    

    6.4提取 JSON 資料

    解構賦值對提取 JSON 物件中的資料,尤其有用。

    // 提取json資料
    let jsonData = {
      id: 42,status: "OK",data: [867,5309]
    };
    
    let {
      id,status,data: number
    } = jsonData;
    
    console.log(id,number); // 42,"OK",[867,5309]
    

    到此這篇關於JS ES新特性之變數的解耦賦值的文章就介紹到這了,更多相關ES變數的解耦賦值內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!