天天看點

ES6中的解構指派1.解構指派理論2.數組的解構指派詳解3.對象的解構指派4.函數參數的解構指派5.解構的用途

目錄

1.解構指派理論

2.數組的解構指派詳解

1.數組解構指派的了解:

 2.解構預設值(有特殊情況bug)

 3.解構嵌套數組

4.相同"模式"的不完全解構 

3.對象的解構指派

1.基本:對象的屬性沒有次序,(重點:變量必須與屬性同名),才能取到正确的值。

2.指派給新變量名 (其中簡寫很重要)

3.對象的不完全解構(對象解構也有的bug)

4.數組和對象的嵌套解構 

5.對象解構的錯誤寫法

4.函數參數的解構指派

1.解構對象類型參數

2.解構數組類型參數

3.為參數設定預設值 

4.注意點:數組注重下标相比對(在乎次序),對象注重相同對象名相比對(不在乎次序) 

5.解構的用途

1. 交換變量值

2.從函數傳回多個值

3.提取JSON資料(使用解構最多的) 

1.解構指派理論

文法是一種 Javascript 表達式。通過解構指派,可以将屬性/值從對象/數組中取出,指派給其他變量。 

也可以說:解析資料源,然後按照資料模型進行取值(左側變量可以多變,隻要總體的資料模型沒變,就能取到右側資料),再指派給變量,也可以稱為聲明變量的進階寫法。

解析:按照資料模型取出資料源中的資料

指派:然後指派給模型變量。 

文法結構:變量修飾符 資料模型 = 資料源;

特點:
  • 解構指派是對指派運算符的擴充。
  • 是一種針對數組或者對象進行模式比對,然後對其中的變量進行指派。
  • 在代碼書寫上簡潔且易讀,語義更加清晰明了;也友善了複雜對象中資料字段擷取。

解構指派隻包括:數組解構和對象解構 

形式:

//數組解構
let [a, b, c] = [1, 2, 3];
//對象解構
let { foo, bar } = { bar: 'bbb' , foo: 'aaa'};
           

說明:在解構指派文法中,"="左側的叫做資料模型,="右側的叫做資料源。

其中:[a, b, c] ,叫做數組的資料模型,{foo, bar}叫做對象的資料模型。

下面對于數組的解構指派和對象的解構指派詳解

2.數組的解構指派詳解

1.數組解構指派的了解:

數組解構是非常簡單簡潔的,在指派表達式的左側使用數組字面量,數組字面量中的每個變量名稱映射為解構數組的相同索引項

<script>
    let [a, b, c] = [1, 2, 3];
    console.log(a);     //1    a映射為右側的相同索引項  就是 1
    console.log(b);     //2    b映射為右側的相同索引項  就是 2
    console.log(c);     //3    c映射為右側的相同索引項  就是 3
</script>
           

 且:我們在擷取擷取數組内的元素時,大多是通過下标的方式

arr[0]

,這種方式也确實友善,但針對特定的情況時,解構會大大提高你的效率

<script>
    //要定義a,b,c,d 4個變量
    let a = 1;
    let b = 2;
    let c = 3;
    let d = 4;    //以前是這樣定義,但現在學了解構後,這顯得麻煩
</script>
           

 一行代碼搞定上面的:

<script>
    let [a,b,c,d] = [1,2,3,4];//以前是這樣定義,但現在學了解構後,這顯得麻煩
    console.log(a,b,c,d);     //1 2 3 4
</script>
           

 2.解構預設值(有特殊情況bug)

如果解構取出的值是

undefined

,可以取設定預設值,沒設定就是取undefined

<script>
    let a, b;
    // 設定預設值
    [a = 5, b = 7] = [1];
    console.log(a); // 1
    console.log(b); // 7
</script>

<script>
    let a, b;
    // 設定預設值
    [a = 5, b] = [1];    //這裡b沒有對應索引值
    console.log(a); // 1
    console.log(b); // undefined
</script>
           

分析:這裡給a,b分别設定的預設值為5和7,因為 左側數組字面量中的變量b,在右側的解構數組中沒有對應的索引值。會得到undefined,但b本身設定了預設值,是以為7

也就是:

有對應索引值取對應索引值,無對應索引值取預設值,無預設值取undefined。

對應索引值優先

索引值其次

最後是undefined

特殊情況1:

但這裡有個bug,如果對應索引值為undefined,也設定了預設值,那是應該取undefined,還是預設值?按照上面的是取對應索引值,這裡對應索引值是undefined,但結果呢?

<script>
    let [a=1,b=2] = [3,undefined];
    console.log(a);     //3
    console.log(b);     //2
</script>
           

結果b取的預設值2,而不是對應索引值, 是以這是一個特殊情況。

特殊情況2:

如果預設值是一個表達式,那麼這個表達式是惰性求值的,即隻有在用到的時候,才會求值(想到函數要在調用的時候才能用到)。 

<script>
    function f() {
        console.log('aaa');
    }
    let [x = f()] = [1];
    console.log(x);       //1
</script>
           

分析:因為x有對應的索引值1,能取到1,是以f()根本就沒運作,是以 不要看到f(),就說函數調用,要根據實際代碼情況分析。

如果把let [x = f()] = [1]; 換成let [x = f()] = [ ]; 最後運作結果就是 "aaa",因為x沒對應索引值,是以x就是預設值,而預設值是f(),函數運作結果為 "aaa"。是以x就是 "aaa"

注意點:

  • 數組的解構是根據它的位置(模式)對應的
  • 解構操作允許有預設值,但一定是已經聲明的。
  • 如果等号的右邊不是數組(或者嚴格地說,不是可周遊的結構)那麼将會報錯

 3.解構嵌套數組

解構嵌套數組,就是模式比對,隻要指派符号"="兩邊的層級結構相同,就可以拿到對應位置的值

<script>
    const arr = [1, [2, 3, [4, 5, 6]]];
    const [a, [b, c, [d, e, f]]] = arr;  //隻要指派符号"="兩邊的層級結構相同,就可以拿到對應位            
                                         //置的值
    console.log(a, b, c, d, e, f);  //1 2 3 4 5 6
</script>
           

4.相同"模式"的不完全解構 

模式相同,但變量沒有完全相同時:

<script>
    //變量不夠,則解構數組中多出的取不到
    let [a, b, c] = [1, 2, 3, 4]; 
    console.log(a,b,c);     // 1 2 3
</script>

<script>
    //變量多了,沒設定預設值,就會取到undefined
    let [a, b, c, d] = [1, 2, 3]; 
    console.log(a,b,c,d);    // 1 2 3 undefined
</script>

<script>
    變量不夠,則解構數組中多出的取不到
    let [a, [b, c, [d, e]]] = [1, [2, 3, [4, 5, 6]]]; 
    console.log(a,b,c,d,e);    // 1 2 3 4 5
</script>
           

3.對象的解構指派

注意點:

1.解構指派是将最小機關的字元設定為變量

<script>
    let obj = {name:"karen",age:22,sons:[{name:'jack',age:1}]};
    let {name,sons:[s1]} = obj;
    console.log(name);  //"karen"
    console.log(s1);    //{name: 'jack', age: 1}
    console.log(sons);  //報錯
</script>
           

分析: let {name,sons:[s1]} = obj; 這段代碼是 将name 和 s1 設定為變量(name和s1為最小機關),而不是把 sons 也設定為變量。是通過sons找到obj的sons成員,是一個數組,取下标為0 的元素{name:'jack',age:1},并将其儲存到變量s1中。

2.解構指派 本質是是一個定義變量的過程:"="左側的資料模型中的變量,不能是同名的

<script>
    let obj = {name:"karen",age:22,sons:[{name:'jack',age:1}]};
    let {name,sons:[{age,name}]} = obj;   //定義了同名的name變量,報錯
                                          Identifier 'name' has already been declared
    console.log(age);
    console.log(name);  
</script>
           

怎麼避免同一個變量呢? 把其中一個變量設定為另一個變量名不就好了麼

利用對象指派給新變量的方法(下面有說)

<script>
    let obj = {name:"karen",age:22,sons:[{name:'jack',age:1}]};
    let {name:name1,sons:[{age,name}]} = obj;  
    console.log(age);    //1
    console.log(name1);  // "karen"
    console.log(name);   //"jack"
</script>
           

1.基本:對象的屬性沒有次序,(重點:變量必須與屬性同名),才能取到正确的值。

<script>
    //變量 foo,bar必須與右側資料源對象的屬性名相同,才能正确解構
    let { foo, bar } = { foo: "aaa", bar: "bbb" };
    console.log(foo);    //變量foo映射為右側的相同屬性名  結果就是 "aaa"
    console.log(bar);    //變量bar映射為右側的相同屬性名  結果就是 "bbb"
</script>
           

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

2.指派給新變量名 (其中簡寫很重要)

當使用對象解構時可以改變變量的名稱或者也可以說成是如果變量名與屬性名不一緻時:

<script>
    let boy = { age: 22, B: true };
    let { age: foo, B: bar } = boy;
    console.log(foo); // 22
    console.log(bar); // true
</script>
           

 分析:let { age: foo, B: bar } =  { age: 22, B: true }; 是對象資料模型(對象字面量)中 age,B在右側源資料中找到對應的資料,然後把右側對應的資料指派給 左側 的變量foo,bar

注意點:age和B不是變量,是以列印出會報錯,真正的變量是foo和bar,age和B隻是與右側資料源的一個對應。

<script>
    let boy = { age: 22, B: true };
    let { age: foo, B: bar } = boy;
    console.log(age); // 報錯  已經沒這個變量了
    console.log(B); //報錯
</script>
           

是以可以得到: 

let { foo, bar } = { foo: "aaa", bar: "bbb" };就是

let { foo:foo, bar:bar} = { foo: "aaa", bar: "bbb" };的簡寫形式

 如果指派給新的對象名,這裡我們可以給這個新的變量名提供一個預設值,如果沒有解構它(右側中沒找到對應的屬性名),就會自動使用預設值

<script>
    let { boy: strong = 22, girl: slim = 21 } = { boy: 30 };
    console.log(strong); // 22
    console.log(slim); // 21
</script>
           
分析:給新的變量名strong和slim設定預設值 22/21.   girl: slim = 21 在右側資料源中沒找到對應的屬性名,就會使用預設值21

3.對象的不完全解構(對象解構也有的bug)

<script>
    let obj = {p: [{y: 'world'}] };
    let {p: [{ y }, x ] } = obj;
    console.log(x);
    console.log(y);
</script>
           
分析:變量y,在右側資料源中能找到對應的屬性名,變量x,沒找到,且x也沒設定預設值,是以會取到undefined 

 對象解構和數組解構都有的bug,設定了預設值,但右側對應資料源值為undefined,此時應該取預設值還是取undefined?

<script>
    let obj = {y:21,x:undefined};
    let {y,x=1} = obj;
    console.log(x); //1
    console.log(y); //21
</script>
           

結果是取預設值,這是一個bug,記住就行 。

總結:一般情況下,有對應屬性名的值(非undefined)就取該值,右側資料源沒有對應屬性名就取設定的預設值,也沒對應屬性名也沒設定預設值,就取undefined。特殊:右側對應屬性名的值為undefined時,取設定的預設值,若沒設定,才取undefined。

4.數組和對象的嵌套解構 

<script>
    const props = [
    { id: 1, name: 'Fizz' },
    { id: 2, name: 'Buzz' },
    { id: 3, name: 'FizzBuzz' },
    ];
    const [, , { name }] = props;
    //const [a,b, { name }] = props;
    console.log(name); // "FizzBuzz"
</script>
           

萬變不離其宗,不管怎麼嵌套,都是在對象和數組解構的基礎上進行,隻要資料模型沒變,改變參數名,最後得到的結果都不會變。比如: const [, , { name }] = props;改為const [a,b, { name }] = props;,參數雖然變了,但是最後結果卻沒變。

5.對象解構的錯誤寫法

<script>
    //這樣寫法是不對的
    let boy;
    {boy} = {boy:1};
</script>
           

 因為JavaScript引擎會将

{boy}

了解為一個代碼塊,進而産生文法錯誤,我們要避免将大括号寫在行首,避免JavaScript将其解釋為代碼塊

正确寫法:

<script>
    let boy;
    ({boy} = {boy: 1});
    console.log();
</script>
           

正确寫法将整個解構指派語句放在一個圓括号(代表是一個整體)裡,就可以正确執行了 

4.函數參數的解構指派

利用解構優化函數調用時中場景:

1.解構對象類型參數

<script>
    function fetch(option){
        var name = option.name;
        var age = option.age;
        var like = option.like;
        console.log(name,age,like);
    }
    fetch({name:"wang",age:20,like:"basketball"});
</script>
//上面這樣寫,可以是可以,顯得比較繁瑣 學了ES6中的解構指派後 下面這樣寫
<script>
    function fetch({ name, age, like }) {
        // 參數經曆了 let { name, age, like } = option
        console.log(name,age,like);
    }
    fetch({name:"wang",age:20,like:"basketball"});
</script>
           

2.解構數組類型參數

<script>
    function add([x, y]) {
	    return x + y;
    }
    add([1, 2]);
</script>
           

3.為參數設定預設值 

 設定預設值,可以避免許多拿不到資料的情況

<script>
    function func({ name = 'wang', age = 22, like = 'basketball' }) {
        console.log(name, age, like);
    }
    const options = { name: 'wang' }
    func(options);     //wang 22 basketball
</script>
           

4.注意點:數組注重下标相比對(在乎次序),對象注重相同對象名相比對(不在乎次序) 

<script>
    //參數是一組有次序的值(比如數組:會嚴格按照下标進行對應取值)
    function f([x, y, z]) {     
        console.log(x);   //1
        console.log(y);   //2
        console.log(z);   //3 
    }
    f([1, 2, 3]);
</script>

<script>
    //參數是一組無次序的值(比如對象:不會按照下标來,隻會找相同屬性,才比對取值)
    function f({a, b, c}) { 
        console.log(a);   //1
        console.log(b);   //2
        console.log(c);   //3
    }
    f({c: 3, b: 2, a: 1});
</script>
           

5.解構的用途

1. 交換變量值

一般已知交換兩個變量的方法:1.設定一個臨時變量 2.利用異或   3.利用數組的解構指派

1.設定一個臨時變量

<script>
    //互動兩個變量的值
    let a = 1;
    let b = 2;
    let temp = a;
    a = b;
    b = temp;
    console.log(a,b);
</script>
           

2.利用異或

3.利用數組的解構指派 

<script>
    let a = 1;
    let b = 3;
    //交換a和b的值
    [a, b] = [b, a];
    console.log(a); // 3
    console.log(b); // 1
</script>
           

2.從函數傳回多個值

函數隻能傳回一個值,如果要傳回多個值,我們隻能将這些值放置數組或對象裡傳回,當我們有了解構指派後,從對象或數組裡取出這些值就很soeasy 

<script>
    // 傳回一個數組
    function exe1() {
        return [1, 2, 3];
    }
    let [a, b, c] = exe1();
    console.log(a,b,c);   //1 2 3
    // 傳回一個對象
    function exe2() {
        return {
            foo: 1,
            bar: 2
        };
    }
    let { foo, bar } = exe2();
    console.log(foo,bar); //1 2
</script>
           

3.提取JSON資料(使用解構最多的) 

 舉例:

<script>
    let sinadata = {
    id: 520,
    statuses: "isOK",
    data: [520, 1314]
    };
    
    //像下面這樣寫可以快速取到想要的資料
    let { id, statuses, data: number } = jsonData;
    console.log(id, status, number);   520, "isOK", [520, 1314]
</script>
           

企業級資料的使用方法:

1.存入一個js檔案裡面,并聲明一個變量來儲存這些資料

ES6中的解構指派1.解構指派理論2.數組的解構指派詳解3.對象的解構指派4.函數參數的解構指派5.解構的用途

2.在html檔案中,引入外部js檔案 

ES6中的解構指派1.解構指派理論2.數組的解構指派詳解3.對象的解構指派4.函數參數的解構指派5.解構的用途

3.将資料列印到控制台中,再利用解構指派進行取資料

ES6中的解構指派1.解構指派理論2.數組的解構指派詳解3.對象的解構指派4.函數參數的解構指派5.解構的用途

注:本文引用了一些其它部落客的作品,它們寫得很好,可以去看看

http://t.csdn.cn/pJPmL

http://t.csdn.cn/ToSA1

繼續閱讀