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会把花括号当成块级作用域来使用就会报错。另外两种则是在内部使用,不会报错。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?