3.解构赋值

1.数组的解构赋值

  ES6允许按照一定的格式对数组、对象进行值的提取、对变量进行赋值,这被称之为解构。

  数组的解构赋值有点那种一对一匹配的味道,如果对应位置没有找到,就会被赋值为undifined。具体可参考以下例子:

 1 let [a,b,c]=[1,2,3]
 2 console.log(a,b,c);//1 2 3
 3 let [a,[b,c]]=[1,[2,3]]
 4 console.log(a,b,c);//1 2 3
 5 let [a,...b]=[1,2,3]
 6 console.log(a,b);//1 [2,3]
 7 let [a,...b]=[1]
 8 console.log(a,b)//1 []
 9 let [a,b]=[1]
10 console.log(a,b)//1 undefined

  在进行解构赋值的时候,也可以进行不完全解构,这也是可以的。如下:

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

  如果等号右边不是数组(或其他不可遍历的结构),在进行解构赋值的时候会报错。如下:

1 let [a]={};//{} is not iterable
2 let [a]=1;//1 is not iterable
3 let [a]=false;//false is not iterable
4 let [a]=null;//null is not iterable

  对于ES6的set结构,它的数据结构类似于数组,可以进行解构赋值,如下:

 1 let [a,b,c] = new Set([1,2,3]) 2 console.log(a,b,c)//1 2 3 

  默认值

  解构赋值允许设置默认值,注:ES6中使用严格相等运算符(===)来进行判断是否存在值,即:这一位置必须为undefined的时候,解构赋值才会去取设置的默认值,其他情况则不会去获取默认值,参考如下:

1 let [a,b=2] = [1]
2 console.log(a,b)//1 2
3 let [a,[b,c=3]]=[1,[2]]
4 console.log(a,b,c)//1 2 3
5 let [a=1]=[null]
6 console.log(a)//null
7 let [a=1]=[undefined]
8 console.log(a)//1

  上述代码可以发现,当设置成null的时候,解构赋值是不会去获取设置的默认值的,只有为undefined的时候才会去获取默认值。

2.对象的解构赋值

  对象的解构赋值和数组的解构赋值有一定的区别,数组的解构赋值是按照下标顺序来进行的,而对象的解构赋值是根据变量名称和对象键名一致进行的赋值,参考如下:

1 let {a,b}={a:1,b:2}
2 console.log(a,b);//1 2
3 let {b,a}={a:1,b:2}
4 console.log(a,b);//1 2

  上述代码可以看出,a,b顺序改变后,实际赋值没有变化。

  对象 的解构赋值可以将对象的方法赋值给某一变量,如下:

 1 let {log} = console;
 2 log("12");//12
 3 
 4 let fun  = {
 5     a:function(){
 6         console.log(1)
 7     },
 8     b:function(){
 9         console.log(2)
10     }
11 }
12 let {a} = fun;
13 a();//1

   在进行解构赋值的时候,如果需要变量名称和对象中的属性名不一致,这时候我们在写解构赋值的时候需要这样写:

let {a:c,b:d} = {
    a:1,
    b:2
}
console.log(c,d)//1 2

  在使用上述代码的时候要注意,在我们这样子写的时候,其中的a、b现在的意义只是解构赋值用来进行匹配的,变量已经变为了c、d。这时候如果我们打印a、b就会报错。 

  嵌套赋值

  解构赋值可以进行相互嵌套,同乡可以获取到值,如下: 

let {a,a:[b,{c}],d} = {
    a:[
        1,
        {c:2},
    ],
    d:2
}
console.log(a,b,c,d)//[1,{c:2},]  1  2  2

  默认值

  对象的解构赋值默认值设置,具体参考如下:

 1 let {a=1}={a:2}
 2 console.log(a)//2
 3 let {a:b=1}={a:2}
 4 console.log(b)//2
 5 let {a=1}={a:null}
 6 console.log(a)//null
 7 let {a=1}={}
 8 console.log(a)//1
 9 let {a=1}={a:undefined}
10 console.log(a)//1

  我们在对已经声明的变量进行解构赋值的时候,有时候会报错,如下:

let a;
{a} = {a:1};// Unexpected token '=' 
({a} = {a:1});//不会报错

  这是因为在上个文章中已经说明,JavaScript会将花括号认为是代码块,当你在外部包上一层小括号后,JavaScript就会正常解析。

  对于数组来说,数组可以看成是一种特殊的对象,它可以适用对象的解构赋值,参考如下:

let arr=[1,2,3]
let {0:a,2:b,3:c} = arr;
console.log(a,b,c)//1 3 undefined

  上述代码的意思:将下标为0的匹配值赋给变量a,下标为2的匹配值赋给变量b,下标为3的匹配值为undifined。

3.字符串的解构赋值

  字符串也可以进行解构赋值,字符串转换为一个类似数组的对象。它进行解构赋值参考如下:

let [a,b,c,d]="你很帅。"
console.log(a,b,c,d);// 你 很 帅 。

 

4.布尔类型和数值类型的解构赋值

let {toString:a}=123;
console.log(a);
console.log(Number.prototype.toString)
console.log(a===Number.prototype.toString)//true
let {toString:b}=true;
console.log(b);
console.log(Boolean.prototype.toString)
console.log(b===Boolean.prototype.toString)//true
let {c}=undefined//Cannot destructure property 'c' of 'undefined' as it is undefined.
let {d}=unll//unll is not defined

  上述代码第一个是数值类型的解构赋值,第二个是布尔类型的解构赋值,可以发现实际上JavaScript在进行解构赋值的时候是吧布尔和数值类型转成了类似对象的格式。null和undifined无法转成对象形式,在使用解构赋值的时候,如果等号右侧仅为null或者undifined,代码会报错。

5.函数参数的解构赋值

  函数的解构赋值具体参考如下:

 1 function fun([a,b]){
 2     console.log(a+b)
 3 }
 4 fun([1,2])//3
 5 function fun({a=1,b=2}){
 6     console.log(a+b)
 7 }
 8 fun({a:5})//7
 9 function fun({a=1,b=2}){
10     console.log(a+b)
11 }
12 fun({a:5,b:6})//11

  值得注意的是,undefined会触发函数的默认值。例:

[1,undefined,2].map((item="yes")=>{
    console.log(item)//1 yes 2
})

  其中map方法设置了默认值“yes”,在遍历到undefined的时候,触发了函数的默认值,故而返回了“yes”。

6.圆括号问题

  ES6规定当在使用解构赋值的时候,如果使用圆括号可能导致解构歧义,就不要使用。我们可以认为能不用就不用。

  不能使用圆括号的情况,如下:

  1.)变量声明时,不能使用圆括号,都会报错,如下例:

let {(a)}={a:1}
let [(a)]=[1]
let {a:(b)}={a:1}
let {(a):b}={a:1}
let {(a:b)}={a:1}

  2.)函数参数也属于变量声明,不能使用圆括号,如下:

function fun([(a)]){
}
function fun({(a)=1}){
}

   3.)赋值语句中使用圆括号,如下:

let a;
({a})={a:1}
([a])=[1]

  上述两种情况的使用都会报错。

  但是在赋值语句中,也有另外几种情况使用是不会报错的,例下:

let a;
({a:q}={a:1})
console.log(q)//1
let b;
[(b)]=[1]
console.log(b)//1
let c;
({c:(e)}={c:1})
console.log(e)//1

  上述几种情况是不会报错的。第一种在上面已经说过,在不加()的情况下,JavaScript会把花括号当成块级作用域来使用就会报错。另外两种则是在内部使用,不会报错。

 

posted @ 2022-10-10 18:07  奔跑的哈密瓜  阅读(94)  评论(0编辑  收藏  举报