ES6解构:es6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称之为解构。
解构赋值是对赋值运算符的扩展。
他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
解构模型
在解构中,有下面两部分参与:
1.解构的源,解构赋值表达式的右边部分。
2.解构的目标,解构赋值表达式的左边部分。
解构赋值
1.数组的解构赋值
var [a,b,c] = [1,2,3];
console.log(a);//1
console.log(b);//2
console.log(c);//3
//本质上这种写法属于‘模式匹配‘,只要等号两边的模式相同,左边的变量就会被赋予对应的值
let [foo,[bar]] = ["111",["abc"]];
console.log(bar); //abc
let [, ,third] = ["foo","bar","baz"];
console.log(third); //baz
let [x,y,z] = ['hah'];
console.log(y); //undefined
//如果解构不成功,变量的值就等于undefined
解构一般有三种情况,完全解构,不完全解构,解构不成功,在上述例子中存在完全解构和解构不成功的例子,下面来看一下不完全解构的例子
let [x,y] = [1,2,3];
console.log(x); //1
console.log(y); //2
let [a,[b],d] = [1,[2,3],4];
console.log(a); //1
console.log(b); //2
console.log(d); //4
//不完全解构:即等号左边的模式,只匹配一部分的等号右边的数组,这种情况下解构依然成功
//如果等号的右边不是数组,或者说不是可遍历的结构,那么将会报错
let [a] = 1;
let [b] = false;
let [c] = NaN;
let [d] = undefined;
let [e] = null;
let [f] = {};
//上面的语句都会报错:Uncaught TypeError: 1 is not iterable
2. 默认值
解构赋值允许指定默认值
let [x,y='b'] = ['a'];
console.log(y); //b
let [x,y = 'b'] = ['a',undefined];
console.log(y); //b ,数组成员为undefined时,默认值仍会生效(因为在ES6内部使用严格相等运算符‘===‘,判断一个位置是否有值,所以当一个数组成员严格等于undefined,默认值才会生效)
let [x,y = 'b'] = ['a',null];
console.log(y); //null,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined
3. 对象的解构赋值
对象的解构与数组有一个重要的不同,数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
//1. 变量名与属性名一致的情况下
let {foo,bar} = {foo : "aaa",bar : "bbb"}
console.log(foo); //aaa
console.log(bar); //bbb
//变量名与属性名不一致的情况下,必须这样写
let {a : name, b : age} = {a : 'zhangsan', b : 33};
console.log(name); //zhangsan
console.log(age); //33
实际上 对象的解构赋值是以这样的形式简写的
let {foo : foo ,bar : bar} = {foo : "aaa",bar : "bbb"}
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋值给对应的变量,真正被赋值的是后者,而不是前者,第一个foo/bar 是匹配的模式,对应的foo/bar属性值才是变量,真正被赋值的是属性值(也就是第二个foo/bar), 如果不能理解再看下面这个例子
const node = {
grand : {
father : {
line : 1,
column : 5
}
}
}
let {grand,grand : { father},grand : {father : {column}}} = node;
console.log(father); // {line : 1, column : 5}
console.log(column); // 5
// grand、fahter、column 分别对这三个属性解构赋值,grand、father是模式,只有column 是变量
4. 字符串的解构赋值
const [a,b,c,d,e] = 'hello';
console.log(a); //h
console.log(b); //e
console.log(c); //l
console.log(d); //l
console.log(e); //o
let { length : len} = 'yahooa';
console.log(len); //5,类似数组的对象都有一个length属性,还可以对这个属性解构赋值
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象,但是等号右边为undefined 和 null时无法转为对象,所以对他们进行解构赋值时,都会报错
let {prop : x } = undefined;
console.log(x); //报错:Uncaught TypeError: Cannot destructure property `prop` of 'undefined' or 'null'
6.函数参数的解构赋值
函数的参数也可以使用解构参数
function move({x = 0,y = 0} = { }){
return [x,y];
}
console.log(move({x : 3,y : 4})); //[3,4]
console.log(move({x : 3})); //[3,0]
console.log(move({})); //[0,0]
console.log(move()); //[0,0]
//move()的参数是一个对象,通过对这个对象进行解构,得到变量x、y的值,如果解构失败,x和y 等于默认值
function move2({x,y} = {x : 1, y : 2 }){
return [x,y];
}
console.log(move2({x : 6,y : 8})); //[6,8]
console.log(move2({})); //[undefined,undefined]
console.log(move2()); //[1,2]
//move2() 是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以与前一种写法的结果不太一样,undefined 就会触发函数的默认值
7.对象解构中的 Rest
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10
b; // 20
rest; // { c: 30, d: 40 }
8.解构对象时会查找原型链(如果属性不在对象自身,将从原型链中查找)
// 声明对象 和 自身 self 属性
var obj = {self: '123'};
// 在原型链中定义一个属性 prot
obj.__proto__.prot = '456';
// test
const {self, prot} = obj;
// self "123"
// prot "456"(访问到了原型链)
解构用途
1.交换变量的值
let x = 1;
let y = 2;
[x,y] = [y,x];
console.log(x); //2
console.log(y); //1
2.从函数返回多个值
函数只能返回一个值,如果要返回多个值的话,只能将它们放在数组或者对象里返回
function example(){
return {
foo : 'a',
bar : 'b'
}
}
let {foo,bar} = example();
console.log(foo); //a
console.log(bar); //b
3. 函数参数的定义
//参数是一组有次序的值
function example([x,y,z]){
return x + y + z;
}
example([1,2,3])
console.log(example([1,2,3])); //6
//参数是一组无次序的值
function f({x,y,z}){
return x + y + z;
}
f({x : 'a', z : 'b', y : 'c' });
console.log(f({x : 'a', z : 'b', y : 'c' })); //acb
4.提取 JSON 数据
解构赋值对提取 JSON 对象中的数据,尤其有用。
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
5.函数参数的默认值
jQuery.ajax = function (url, {
async = true,
beforeSend = function () {},
cache = true,
complete = function () {},
crossDomain = false,
global = true,
// ... more config
} = {}) {
// ... do stuff
};
指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || ‘default foo’;这样的语句。
6.遍历 Map 结构
任何部署了 Iterator 接口的对象,都可以用for…of循环遍历。Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便。
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
// first is hello
// second is world
如果只想获取键名,或者只想获取键值,可以写成下面这样。
// 获取键名
for (let [key] of map) {
// ...
}
// 获取键值
for (let [,value] of map) {
// ...
}
7.输入模块的指定方法
加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
const { SourceMapConsumer, SourceNode } = require("source-map");
来源:CSDN
作者:A-Select �
链接:https://blog.csdn.net/weixin_45959504/article/details/104779139