es6提供了一个很是好的特性,即变量的解构赋值。从而咱们能够方便的从数组和对象中提取数据并将它们赋值给变量。这是很是必要的。先来看在这个新特性发布以前咱们是如何从数组中提取数据的。以下:javascript
let nums = [1,2,3,4,5];
let num1 = nums[0];
let num2 = nums[1];
console.log(num1); // logs 1
console.log(num2); // logs 2
复制代码
为了从 nums
数组中提取到数据,咱们屡次重复着相同的代码。es6的解构赋值将会让这个操做变得很是的容易且易于理解。java
从数组中取值并按照对应位置对变量进行赋值。以下:es6
let [num1,num2,num3] = [1,2,3];
console.log({num1},{num2},{num3})
复制代码
这属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。数组
let [num_s,nums,num_e] = [1,[2,3,4],5];
console.log(num_s) // logs 1
console.log(nums) // logs [2,3,4]
console.log(num_e) // logs 5
复制代码
let [num1,,,num4] = [1,2,3,4];
console.log(num1) // logs 1
console.log(num4) // logs 4
let [,num2,,num4] = [1,2,3,4];
console.log(num2) // logs 2
console.log(num4) // logs 4
复制代码
查看变量赋值左侧的数组。注意这里不是只有一个逗号,而是三个。逗号分隔符用于跳过数组中的值。因此若是你想要跳过数组中的一个项,只要用逗号就能够了。函数
若是咱们想将数组中的一些元素赋值给变量,而将数组中的其他元素存为一个数组赋值给指定的变量怎么办?在这种状况下,咱们能够这样作:ui
let [num1,...nums] = [1,2,3,4];
console.log(num1) // logs 1
console.log(nums) // logs [2,3,4]
复制代码
应用这种方式,你能够轻松的把剩余的元素赋值给一个指定的变量。spa
undefined
let [num1] = [];
let [num2, num3] = [1];
console.log(num1) // logs undefined
console.log(num3) // logs undefined
复制代码
代码中的变量num1
与变量num3
按照模式匹配原则,并无对应的值与之匹配,故而返回undefined
。而变量num2
按照模式匹配原则,被赋值为2。3d
解构赋值还能够从函数返回的数组中提取数据。假设咱们有一个返回数组的函数,以下例所示:code
function getLists() {
let lists = [1,2,3,4,5]
return lists;
}
let [num1,...nums] = getLists();
console.log(num1); // logs 1
console.log(nums); // logs [2,3,4,5]
复制代码
数组的解构赋值能够给变量设定默认值,以防万一从数组中提取的值是 undefined
(防止解构失败的状况)cdn
let [name = "暂无姓名",sex = "女"] = ["April"];
console.log(name); // "April"
console.log(sex); // "女"
复制代码
代码中变量name
默认的值为 "暂无姓名"
可是按照左右模式匹配的原则,name
被赋值为 "April"
,由于变量sex
并未匹配到值,因此它的值依旧是默认值"女"
。
注意点1:ES6 内部使用严格相等运算符(===
),判断一个位置是否有值。因此,只有当一个数组成员严格等于undefined
,默认值才会生效。
let [num1 = 1] = [undefined];
console.log(num1) // logs 1
let [num2 = 2] = [null];
console.log(num2) // logs null
复制代码
代码中,由于null
不严格等于undefined
,默认值就不会生效。故而输出了 null
注意点2:若是默认值是函数,这个函数就会很是的懒,即只有在用到的时候,才会执行函数。
function getLists(){
let lists = [1,2,3,4,5]
return lists;
}
let [lists = getLists()] = [1];
console.log(lists) // logs 1
// 由于变量 lists 能够匹配到值,因此函数 getLists() 并不会执行。
function getLists(){
let lists = [1,2,3,4,5]
return lists;
}
let [lists = getLists()] = [];
console.log(lists) // logs [1,2,3,4,5]
// 由于变量 lists 没法匹配到值,函数 getLists() 就会执行。故而返回数据 [1,2,3,4,5]
复制代码
注意点3:默认值能够引用解构赋值的其余变量,但该变量必须已经声明。
let [x = 1, y = x] = []; // logs x=1; y=1
let [x = 1, y = x] = [2]; // logs x=2; y=2
let [x = 1, y = x] = [1, 2]; // logs x=1; y=2
let [x = y, y = 1] = []; //logs 这就要报错啦,由于x用y作默认值时,y尚未声明。
复制代码
let num1 = 1;
let num2 = 2;
[num1,num2] = [num2,num1];
console.log({num1}); // logs 2
console.log({num2}); // logs 1
复制代码
为何要用对象的解构赋值呢??
let profiles = {
name:'April',
nickname:"二十七刻",
sign:"不以物喜,不以己悲。"
}
let name = profiles.name;
let nickname = profiles.nickname;
let sign = profiles.sign;
console.log({name}) // "April"
console.log({nickname})// "二十七刻"
console.log({sign}) // "不以物喜,不以己悲。"
复制代码
假设咱们要从对象profiles
中获取数据并赋值给新变量。就得不断的重复着取值与赋值。代码冗长且不利于维护。利用对象的解构赋值,就不存在这一问题了。
对象的解构赋值变量必须与属性同名,才能取到正确的值。以下:
let profiles = {
name:'April',
nickname:"二十七刻",
sign:"不以物喜,不以己悲。"
}
let {name,nickname,sign} = profiles;
console.log({name}) // logs "April"
console.log({nickname})// logs "二十七刻"
console.log({sign}) // logs "不以物喜,不以己悲。"
复制代码
undefined
let profiles = {
name:'April',
nickname:"二十七刻",
sign:"不以物喜,不以己悲。"
}
let {name,sex} = profiles;
console.log(name) // logs "April"
console.log(sex) // logs undefined
复制代码
上面代码中,由于profiles
对象没有 sex
属性,因此变量sex
取不到值,因此就赋值undefined
。
在对象的解构赋值中,变量能够在赋值以前申明。以下:
let profiles = {
name:'April',
nickname:"二十七刻",
sign:"不以物喜,不以己悲。"
}
let name,nickname,sign;
{name,nickname,sign} = profiles;
console.log(name) // logs Error : "Unexpected token ="
复制代码
嘿呀~报错了!为何???
缘由:由于忘记在{}
外层写()
了。
注意1 :当使用没有声明的对象字面量解构赋值时,必须使用()
的赋值语句。由于 JavaScript 引擎会将{name,nickname,sign}
理解成一个代码块,而不是对象字面量。
注意2 :使用此语法时,上一行代码必定要以;
结束掉,不然的话会被看成函数,执行上一行的代码。
就是这个奇怪的语法 :({} = '');
正确的作法以下:
let profiles = {
name:'April',
nickname:"二十七刻",
sign:"不以物喜,不以己悲。"
}
let name,nickname,sign;
({name,nickname,sign} = profiles);
console.log({name},{nickname},{sign})
// logs {name: "April"} {nickname: "二十七刻"} {sign: "不以物喜,不以己悲。"}
复制代码
若是咱们想用新的变量名来替代对象的属性名怎么办呢?代码以下:
let profiles = {
name:"April",
age:"27"
}
let {name:userName,age:userAge} = profiles;
console.log(userName) // logs "April"
console.log(userAge) // logs "27"
复制代码
由此可知,对象的解构赋值其实就是let {name:name,age:age} = {name:"April",age:"27"}
代码的简写。也就是说,对象的解构赋值的内部机制,是先找到同名属性,而后再赋给对应的变量。真正被赋值的是后者,而不是前者。
上面代码中,name
是匹配的模式,userName
才是变量。真正被赋值的是变量userName
,而不是模式name
。
对象的解构赋值能够给变量设定默认值,以防万一从对象中获取的值是 undefined
(防止解构失败的状况)须要注意的是:默认值生效的条件是,对象的属性值严格等于undefined
。
let staff = {name: "April", country: "China", job: "Developer"};
let {name = "暂无姓名", age = "暂无年龄"} = staff;
console.log({name}); // logs "April"
console.log({age}); // logs "暂无年龄"
复制代码
代码中变量name
的默认值为“暂无姓名”,可是对象staff
中有属性为name
的字段,因此就被赋值April
,而对象staff
中并无age
这个属性,因此被赋值为"暂无年龄",取了它本身的默认值。
计算属性名是另外一个对象特性,也适用于对象的解构赋值。你能够经过一个表达式指定一个属性的名称,把它放在[]
中,以下:
let staff = {name: "April", country: "China", job: "Developer"};
let prop = "name";
let {[prop]: name} = staff;
console.log({name}); // logs "April"
复制代码
解构运算也能够被应运到解构赋值当中,来获取那些尚未被赋值的键值对,这些键值对都被放在一个新的对象里。以下:
let staff = {name: "April", country: "China", job: "Developer",nickname:"二十七刻"};
let {country,...infos} = staff;
console.log(country) //logs "China"
console.log(infos) // logs {name: "April", job: "Developer", nickname: "二十七刻"}
复制代码
let staffs = {
group1:[ { id:"007", name:"April"}]
}
let {group1,group1:[{id,name}]} = staffs;
console.log(group1) // logs [{ id:"007", name:"April"}]
console.log(id) // logs "007"
console.log(name) // logs "April"
复制代码
注意,代码中group1
是模式,不是变量。若是想把group1
也做为变量赋值,就要先进行定义再去赋值。
数组和对象的解构赋值,本文就总结这么多。不足之处,万望指出。