前言
ES6(ECMAScript 2015)引入了许多新的语法特性,其中之一就是变量的解构赋值。这个特性使得在声明和赋值变量时更加灵活和方便。
我们在之前的文章当中,已经浅学过如何对数组和对象进行解构。今天,我来进行拓展和补充!
之前的文章可以参考:潜聊ES6新特性--解构【干货】 - 掘金 (juejin.cn)
正文
ES6(ECMAScript 2015)引入了许多新的语法特性,其中之一就是变量的结构赋值。这个特性使得在声明和赋值变量时更加灵活和方便。
一、数组的解构赋值
数组的解构赋值是 ES6 中引入的一项强大功能,它使得从数组中提取值并赋给变量变得更加简洁和灵活。
接下来,我们通过案例来进行学习!
以前我们的赋值方式:
js
let a = 1
let b = 2
let c = 3
但是在ES6当中,允许我们这样赋值!
js
let [a,b,c]=[1,2,3]
console.log(a);//输出:1
console.log(b);//输出:2
console.log(c);//输出:3
这一点其实,我们在潜聊的时候,我们就聊过了,并且这种方式,a
,b
,c
的取值也是会取到数组的中的对应位置的值!
这里,我们就要聊到模式匹配了!
数组模式匹配是一种通过模式匹配语法从数组中提取值的方法。通过方括号内的变量名,我们可以将数组中对应位置的值赋给相应的变量。
也就是说,我们可以忽略某些元素.
1. 忽略某些元素
js
let [a,,c]=[1,2,3,4]
console.log(a);//输出:1
console.log(c);//输出:3
我可以这样来进行模式匹配!甚至是...
的解构方法!这种方式是是剩余元素的获取.
2. 剩余元素
js
let [a,...c]=[1,2,3,4]
console.log(a);//输出:1
console.log(c);//输出:[ 2, 3, 4 ]
这其实就是一种解构方法!假如解构不成功呢?那么输出的毫无疑问就是undefined
我们来看看案例:
js
let [,,,,a]=[1,2,3,4]
console.log(a);//输出:undefined
当然,还有不完全解构这个概念,解构的过程并没有把数组中的所有数据都解构出来!这也是可以成功的!
3. 不完全解构
js
let [a,b,c]=[1,2,3,4]
console.log(a);//输出:1
console.log(b);//输出:2
console.log(c);//输出:3
注意,当我们使用let [变量] = []
这种方式进行解构的时候,如果等号右边不是数组[]
,那么我们的编译器将会报错!严格来说是不可遍历的结构!
还有一种嵌套的解构方式!
4.嵌套数组模式匹配
js
let [a, [b, c], d] = [1, [2, 3], 4];
console.log(a); //输出:1
console.log(b); //输出:2
console.log(c); //输出:3
console.log(d); //输出:4
实际上,只要是具有Iterator接口的数据结构类型都可以采用数组结构的方式进行解构!比如Set
结构!
js
let set = new Set([1,2,3]);
let [a,b,c]=set
console.log(a);//输出:1
console.log(b);//输出:2
console.log(c);//输出:3
5. 默认值
数组模式匹配也支持设置默认值,当解构的值为 undefined
时,变量会取默认值。
js
javascriptCopy codelet [a, b, c = 3] = [1, 2];
console.log(c); // 3
在这个例子中,由于数组中并没有第三个元素,所以变量 c
取到了默认值 3。
但是在默认值当中,有两种情况,我们要看看结果!
js
let [a=1]=[undefined]
let [b=2]=[null]
console.log(a);//输出:1
console.log(b);//输出:null
如果一个数组成员是null
,默认值就不会生效,因为null
不严格等于undefined
。所以null
会替代掉我们设置的默认值!
当然还有函数比较特殊!
js
function foo(){}
let [a = foo()]=[1]
console.log(a);//输出:1
其实,这就等价于:
js
let a;
if ([1][0] === undefined) {
a = foo();
} else {
a = [1][0];
}
默认值也赋值为其他解构变量,前提是这个变量已经声明!
js
let [a=1,b=a] = []
console.log(a);//输出:1
console.log(b);//输出:1
二、对象的解构
在之前的文章,我们也介绍了对象的解构方式,今日我再学习一遍!
与数组类似,我们可以差不多这种方式对对象进行解构!但是又有点不同!
我们来看看:
js
let obj = {name:'小明',age:19}
let {name:name,age:age}=obj
// 也可以写成这样
let {name,age} = obj
console.log(name);//输出:小明
console.log(age);//输出:19
对象可以不按次序进行解构,而数组是按次序解构,数组中变量的取值是按次序而定,而对象中,变量必须要于属性同名,才能取到你想要的值。
如果解构得不到值,会输出undefined
,如下:
js
let obj = {name:'小明',age:19}
let {address}=obj
console.log(address);//输出:undefined
因为我们的对象obj
中没有address
这个属性,所以变量address
取不到值。
1、修改变量名
我们再解构的时候,也可以修改变量名,但是必须写成以下这种格式!
js
let obj = {name:'小明',age:19}
let {name:名字,age:年龄}=obj
console.log(名字);//输出:小明
console.log(年龄);//输出:19
其中name
和age
是匹配模式,用于匹配对象中的key
值,名字
,年龄
是我们设定的变量名!
2、嵌套结构的对象
和数组一样,对象可以对具有嵌套结构的对象进行解构!我们来给大家看看一个案例!
js
let obj =
{name:'小明',
age:19,
like:{
like1:'coding',
unlike:{
unlike1:'play games'
}
}
}
let {
name,
age,
like:{
like1,
unlike:{
unlike1
}
}
} = obj;
console.log(name);//输出:小明
console.log(age);//输出:19
console.log(like1);//输出:coding
console.log(unlike1);//输出:play games
注意!like
和unlike
是匹配模式,不是变量,不会对其进行赋值!假如我们要对like
这种key
进行赋值该如何操作呢?我们来上一个简单的案例!
js
let obj = {like:{like1:'coding'}}
let {like,like:{like1}} = obj
console.log(like);//输出:{ like1: 'coding' }
console.log(like1);//输出:coding
这样,我们就也能对like
赋值成为一个变量了!如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
js
let obj = {like:{like1:'coding'}}
let {unlike:{like1}}//报错
3、默认值
和数组一样,对象解构也能具备默认值!我们直接来看案例吧!
js
let obj = {name:'小明'}
let {name='小红',age = 19}=obj
console.log(name);//输出:小明
console.log(age);//输出:19
如果我们声明的变量有默认值,并且在对象中能解构出一个对应的key
值,那么这个默认值将会被覆盖!如果没有这样一个key
值与我们声明的变量进行匹配,那么这个变量将会被设为默认值!
4、获取对象的方法
我们可以通过设置一个变量,来获取对象当中的方法,当然变量名要与方法名进行匹配!
js
let {max} = Math
console.log(max(1,100));//输出:100
例如,我们这个案例当中,我们用max
这样的变量获取Math
对象当中的max
方法!这样我们就可以直接拿着max
方法进行使用啦!
5、获取对象继承的属性
我们也可以通过对象解构,获取到对象继承的方法!例如:
js
let obj = {}
let obj2 ={fn:function(){}}
Object.setPrototypeOf(obj, obj2);//将obj的原型设为obj2
let {fn} = obj
console.log(fn);//输出:[Function: fn]
我们在这个案例里面,将obj
的原型设置为obj2
,在用一个变量fn
获取到了obj
原型中的属性!
当然在对象解构的时候!有三个注意的点!
一、用以声明的对象要注意写法!
js
// 错误的写法
let x;
{x} = {x: 1};//会报错:SyntaxError: syntax error
//正确的写法
let x;
({x} = {x:1});
这是为什么呢?这是因为当我们使用已经声明的变量!我们要注意写法!为什么呢?因为我们的JavaScript编译器会把{x}
理解成一个单独的代码块!所以我们要加一个()
避免JavaScript编译器将其识别为代码块!
二、解构赋值语句,右边部分可以不防止任何东西!这样就会出现一些奇奇怪怪的代码!
例如:
js
let obj = {name:'小明'}
let {} = obj
虽然这种代码没有任何意义,但是的的确确是合法的,也可以正常运行!
三、数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
我们来看看案例!
js
let arr = [1,2,3]
let {0:first,1:next,2:last} = arr
console.log(first);//输出:1
console.log(next);//输出:2
console.log(last);//输出:3
对于数组,我们使用对象的解构方法,对应的key
值其实就是数组的下标!
三、字符串的解构赋值
其实,字符串的解构就有点类似数组了!
js
let str = 'coding'
let [a,b,c,d,e,f]= str
console.log(a);//输出:c
console.log(b);//输出:o
console.log(c);//输出:d
console.log(d);//输出:i
console.log(e);//输出:n
console.log(f);//输出:g
同时,类似数组的对象都有一个length
属性,我们可以对这个属性进行解构!
js
let str = 'coding'
let {length:len}= str
console.log(len);//输出:6
注意!我们这里要使用对象的花括号{}
,而不是数组的方括号[]
四、数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值或者布尔值,则会先转为对象。
javascript
let {toString: num} = 666;
console.log( num === Number.prototype.toString) //输出:true
let {toString: bol} = true;
console.log( bol === Boolean.prototype.toString) //输出:true
上述案例当中,数值和布尔值的包装对象都有toString
属性,因此变量num
和bol
都能取到值。
当我们使用解构赋值时,如果等号右边的值不是对象或数组,JavaScript 会尝试将其转为对象。然而,由于 undefined
和 null
无法被转为对象,因此在对它们进行解构赋值时,会导致错误。简而言之,试图对 undefined
或 null
进行解构赋值会引发错误。
上案例:
javascript
let { prop: un } = undefined; // 会抛出TypeError
let { prop: nu } = null; // 会抛出TypeError
五、函数参数的解构赋值
函数的参数也是可以解构赋值的!
javascript
function num([a,b]){
console.log(a);//输出:1
console.log(b);//输出:2
}
num([1,2])
在我们上面的例子当中,我们的函数num
表面上接收了一个数组,其实对于函数体内部来说,接收的是一个解构后的数组,也就是接收了两个变量a
,b
同样的,函数的解构也可以使用默认值!
js
function num([a = 2,b = 3]){
console.log(a);//输出:1
console.log(b);//输出:3
}
num([1])
在上述案例当中,我们为函数的形参b
提供了一个默认值 3 ,因为我们没有给形参b
传一个实参,所以在解构的时候,变量b
就采用了默认值!而形参a
,我们为它传了一个实参,所以默认值就会被我们传的值所覆盖!
其实函数解构还有更多写法!大家可以自主去学习一下!
六、总结:用途
-
数组解构:
- 从数组中提取值,赋值给变量,使代码更简洁易读。
- 允许跳过不需要的元素,通过逗号占位符。
- 支持默认值,用于处理数组中可能不存在的元素。
-
对象解构:
- 从对象中提取属性值,以便更方便地使用这些值。
- 可以使用别名,使得变量名更具有描述性。
- 也支持默认值,处理可能不存在的属性。
-
函数参数解构:
- 允许函数参数直接从传入的对象或数组中提取值,提高函数参数的可读性。
- 可以使用默认值,处理缺失的参数。
-
嵌套解构:
- 处理嵌套的数据结构,如对象中嵌套对象或数组,使得提取数据更便利。
-
剩余/扩展操作符:
- 使用剩余操作符可以获取数组中的其余元素,使得处理动态长度的数组更方便。
- 扩展操作符可以用于合并数组或对象。
-
交换变量值:
- 使用解构可以更简洁地交换两个变量的值,而无需借助中间变量。
javascript
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 输出: 2 1
- 提取函数返回的对象属性:
- 从函数返回的对象中直接提取属性,避免了临时变量的使用。
javascript
function getUser() {
return { id: 1, name: 'John' };
}
const { id, name } = getUser();
console.log(id, name); // 输出: 1 John
- 多值返回:
- 函数可以返回多个值,然后通过解构一次性获取这些值。
javascript
function getValues() {
return [1, 2, 3];
}
const [x, y, z] = getValues();
console.log(x, y, z); // 输出: 1 2 3
好了,我们今天的学习就到这里了!欢迎大家评论留言哦!
点个赞鼓励支持一下吧!🌹🌹🌹 引用参考:ES6 入门教程 - ECMAScript 6入门 (ruanyifeng.com)