ECMAScript6 - 2.變量的解構賦值

1.數組解構賦值

1.1.基本用法

// (1)對數組變量賦值
      let [foo, [[bar], baz]] = [1, [[2], 3]];
      foo; // 1
      bar; // 2
      baz; // 3

      let [, , third1] = ["foo", "bar", "baz"];
      third1; // "baz"

      let [aa, , bb] = [1, 2, 3];
      aa; // 1
      bb; // 3

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

      //(2)解構不成功(變量數 > 賦值數) 1.
      let [x, y, ...z] = ["a"];
      x; // "a"
      y; // undefined
      z; // []

      //解構不成功 2.
      let [foo1] = [];
      let [bar1, foo2] = [1];
      foo1; // undefined
      bar1; // 1
      foo2; // undefined

      //(3)解構不徹底(變量數 < 賦值數) 1.
      let [x1, y1] = [1, 2, 3];
      x1; // 1
      y1; // 2

      //解構不徹底 2.
      let [a, [b], d] = [1, [2, 3], 4];
      a; // 1
      b; // 2
      d; // 4

      //(4)若是等號的右邊不是數組-->報錯
      //   let [foo] = 1;
      //   let [foo] = false;
      //   let [foo] = NaN;
      //   let [foo] = undefined;
      //   let [foo] = null;
      //   let [foo] = {};

      //(5) Set 結構,也可使用數組的解構賦值
      let [e, f, g] = new Set(["a", "b", "c"]);
      e; // "a"
      f; // "b"
      g; // "c"

      // (6) 只要某種數據結構具備 Iterator 接口,均可以採用數組形式的解構賦值。
      function* fibs() {
        let a = 0;
        let b = 1;
        while (true) {
          yield a;
          [a, b] = [b, a + b];
        }
      }

      let [first, second, third, fourth, fifth, sixth] = fibs();
      sixth; // 5

1.2.默認值

{
        let [foo = true] = [];
        foo; // true

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

      // (2)ES6 內部使用嚴格相等運算符(===),判斷一個位置是否有值。只有當一個數組成員嚴格等於undefined,默認值纔會生效。
      {
        let [x = 1] = [undefined];
        x; // 1

        let [y = 1] = [null];
        y; // null    若是一個數組成員是null,默認值就不會生效,由於null不嚴格等於undefined。
      }

      // (3)默認值是一個表達式,那麼這個表達式是惰性求值的,即只有在用到的時候,纔會求值。
      function f() {
        console.log("aaa");
      }

      let [x = f()] = [1];
      x;

      //等價於上面  let [x = f()] = [1];
      let y;
      if ([1][0] === undefined) {
        y = f();
      } else {
        y = [1][0];
      }

      // (4)默認值能夠引用解構賦值的其餘變量,但該變量必須已經聲明。
      let [c = 1, d = c] = []; // c=1; d=1
      let [e = 1, g = e] = [2]; // e=2; g=2
      let [h = 1, i = h] = [1, 2]; // h=1; i=2
      let [j = k, k = 1] = []; // ReferenceError: k is not defined  -> k沒有聲明

對象

//(1) 基礎用法
      {
        let { foo, bar } = { foo: "aaa", bar: "bbb" }; //等價於 let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
        foo; // "aaa"
        bar; // "bbb"
      }

      //(2) 變量名與屬性名不一致:錯誤寫法
      {
        let { bar, foo } = { foo: "aaa", bar: "bbb" };
        foo; // "aaa"
        bar; // "bbb"

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

      //(3) 變量名與屬性名不一致:正確寫法
      {
        let { foo: baz } = { foo: "aaa", bar: "bbb" };
        baz; // "aaa"
        // foo是匹配的模式,baz纔是變量。真正被賦值的是變量baz,而不是模式foo。

        let obj = { first: "hello", last: "world" };
        let { first: f, last: l } = obj;
        f; // 'hello'
        l; // 'world'
      }

      //(4) 嵌套結構:數組同樣,解構也能夠用於嵌套結構的對象。 這時p是模式,不是變量,所以不會被賦值
      {
        let obj = {
          p: ["Hello", { y: "World" }]
        };

        let {
          p: [x, { y }]
        } = obj;
        x; // "Hello"
        y; // "World"
      }

      //(5) 嵌套結構:若是p也要做爲變量賦值,能夠寫成下面這樣。
      {
        let obj = {
          p: ["Hello", { y: "World" }]
        };

        let {
          p,
          p: [x, { y }]
        } = obj;
        x; // "Hello"
        y; // "World"
        p; // ["Hello", {y: "World"}]
      }

      //(6) 只有line是變量,loc和start都是模式
      {
        const node = {
          loc: {
            start: {
              line: 1,
              column: 5
            }
          }
        };

        let {
          loc,
          loc: { start },
          loc: {
            start: { line }
          }
        } = node;
        line; // 1
        loc; // Object {start: Object}
        start; // Object {line: 1, column: 5}
      }

      //(7) 嵌套賦值:
      {
        let obj = {};
        let arr = [];

        ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

        obj; // {prop:123}
        arr; // [true]
      }
      //(8) 默認值
      {
        var { x = 3 } = {};
        x; // 3

        var { a, b = 5 } = { a: 1 };
        a; // 1
        b; // 5

        var { c: d = 3 } = {};
        d; // 3

        var { e: f = 3 } = { e: 5 };
        f; // 5

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

      //(9) 默認值生效的條件是,對象的屬性值嚴格等於undefined。
      {
        var { x = 3 } = { x: 4 };
        x; // 3

        var { y = 3 } = { y: null };
        y; // null
      }

      //(10) 解構失敗
      {
        let { foo } = { bar: "baz" };
        foo; // undefined
      }

      //(11) 嵌套的對象,並且子對象所在的父屬性不存在
      {
        //// 報錯,等號左邊對象的foo屬性,對應一個子對象。該子對象的bar屬性,解構時會報錯。緣由很簡單,由於foo這時等於undefined,再取子屬性就會報錯,
        // let {
        //   foo: { bar }
        // } = { baz: "baz" };
        //// 對上面的解讀
        // let _tmp = { baz: "baz" };
        // _tmp.foo.bar; // 報錯 _tmp.foo = undefined 再取子屬性就會報錯
      }

      //(12) 已經聲明的變量用於解構賦值
      {
        let x;
        // 錯誤的寫法
        // {x} = {x: 1};   這裏{x} 被理解爲代碼塊

        // 正確的寫法
        ({ x } = { x: 1 });
        console.log(x);
        // SyntaxError: syntax error
      }

      //(13) 解構賦值容許等號左邊的模式之中,不放置任何變量名 -> 雖然毫無心義,可是語法是合法的,能夠執行。
      {
        ({} = [true, false]);
        ({} = "abc");
        ({} = []);
      }

      //(14) 代碼將Math對象的對數、正弦、餘弦三個方法,賦值到對應的變量上,使用起來就會方便不少。
      let { log, sin, cos, PI } = Math;
      console.log(sin); //sin() { [native code] }
      console.log(PI); //3.141592653589793

      //(15) 因爲數組本質是特殊的對象,所以能夠對數組進行對象屬性的解構。
      //上面代碼對數組進行對象解構。數組arr的0鍵對應的值是1,[arr.length - 1]就是2鍵,對應的值是3。方括號這種寫法,屬於「屬性名錶達式」
      let arr = [1, 2, 3];
      let { 0: first, [arr.length - 1]: last } = arr;
      first; // 1
      last; // 3
相關文章
相關標籤/搜索