数组的解构赋值
基本语法与解构结果说明
正常解构赋值与结果展示
let x = {
a: 1
};
const [a, b, c] = [{
a: 1,
b: 2
},
[1, 2, 3],
function() {
console.log(1111112)
}
];
console.log(a); //{a:1,b:2}
console.log(b); //[1,2,3]
c(); //1111112
解构不成功
不会报错,undefined
let [foo1] = [];
let [bar, foo2] = [1];
console.log("foo1", foo1); //undefined
console.log("bar", bar); //1
console.log("foo2", foo2); //undefined
不完全解构
左边只能匹配右边部分,
let [x1, x2] = [1, 2, 3];
console.log(x1); //1
console.log(x2); //2
解构报错
转换成对象后没有Iterator接口
let [foo3] = 1;
let [foo4] = false;
let [foo5] = NaN;
let [foo6] = undefined;
let [foo7] = null;
let [foo8] = {};
Set结构也可以使用数组的解构赋值
只要具备Iterator接口,就可以采用数组形式的解构赋值
let [x,y,z] = new Set(['a','a','c']);
console.log(x); // a
console.log(y); // c
console.log(z); //undefined
默认值
解构赋值允许指定默认值
let [defaultA = 'true',defaultB] = [,'a'];
console.log(defaultA,defaultB); //true,a
只有当所赋值为严格意义上的undefined时,默认值才会生效
let [defaultUndefined1,defaultUndefined2 = 1] = [2,null];
console.log(defaultUndefined1); // 2
console.log(defaultUndefined2); // null
默认值为一个表达式
function f() {
console.log("blabla");
}
let [expressX = f()] = [1];
console.log(expressX); // 1,函数未执行
对象的解构赋值
基本语法
let {first, second, middle, last} = {first:'莫', middle: '笑', last: '忘'};
console.log(first); //莫
console.log(middle); //笑
console.log(last); //忘
console.log(second); //undefined
对象的属性名无次序,没有对应属性名可匹配,则赋值为undefined;
如果变量名与属性名不一致,形式如下:
let {first: firstName} = {first:'莫'};
console.log(firstName); //莫
console.log(first); //报错
在以上解构赋值代码中,first为匹配的模式,firstName才是要被赋值的变量;
嵌套对象的解构赋值:
let obj = {
p: [
'Hello',
{
y: 'World'
}
]
};
let {
p: [x, {
y
}]
} = obj;
console.log(x); // hello
console.log(y); //world
如果希望p也作为变量赋值:
let { p, p: [x, { y }] } = obj;
如果解构模式是嵌套的对象,而且自对象的父属性不存在,会报错
let {name: {first}} = {gender: 'female'}; //报错
对象的解构赋值可以取到继承的属性;可以指定默认值,生效的条件为对象的属性值严格等于undefined;
如果将一个已经声明的变量用于结构赋值,需注意:
// 错误的写法
let x;
{x} = {x: 1};
原因:js引擎将{x}理解成一个代码块,所以发生语法错误,所以不将{}防砸行首:
let x;
({x} = {x: 1});
解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式,虽毫无意义,但是合法。也可以对数组进行对象属性的解构:
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
字符串的解构赋值
字符串被转换成了一个类似数组的对象
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值:
let {length : len} = 'hello';
len // 5
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象:
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错:
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
函数参数的解构赋值
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
圆括号问题
ES6 的规则是,只要有可能导致解构的歧义,就不得使用圆括号。
建议只要有可能,就不要在模式中放置圆括号。
不能使用圆括号的情况
变量声明语句
变量声明语句,模式不能使用圆括号
// 全部报错
let [(a)] = [1];
let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};
let { o: ({ p: p }) } = { o: { p: 2 } };
函数参数
函数参数也属于变量声明,因此不能带有圆括号
// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }
赋值语句的模式
// 全部报错
({ p: a }) = { p: 42 };
([a]) = [5];
[({ p: a }), { x: c }] = [{}, {}];
可以使用圆括号的情况
赋值语句的非模式部分,可以使用圆括号
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确
以上特征1:赋值语句;2:圆括号不属于模式的一部分
用途
交换变量的值
简便直观
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x); //2
console.log(y); //1
从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
函数参数的定义
我怎么觉得这个用途没甚意义呢
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
提取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]
函数参数的默认值
可以避免在函数体内再对参数进行默认赋值等
function ({a=1,b=2} = {}){
//BLABLA
}
遍历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) {
// ...
}
输入模块的指定方法
加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰
(这个好像很少用啊,像我现在是这样)
const { SourceMapConsumer, SourceNode } = require("source-map");
数组的解构赋值
基本语法与解构结果说明
正常解构赋值与结果展示
let x = {
a: 1
};
const [a, b, c] = [{
a: 1,
b: 2
},
[1, 2, 3],
function() {
console.log(1111112)
}
];
console.log(a); //{a:1,b:2}
console.log(b); //[1,2,3]
c(); //1111112
解构不成功
不会报错,undefined
let [foo1] = [];
let [bar, foo2] = [1];
console.log("foo1", foo1); //undefined
console.log("bar", bar); //1
console.log("foo2", foo2); //undefined
不完全解构
左边只能匹配右边部分,
let [x1, x2] = [1, 2, 3];
console.log(x1); //1
console.log(x2); //2
解构报错
转换成对象后没有Iterator接口
let [foo3] = 1;
let [foo4] = false;
let [foo5] = NaN;
let [foo6] = undefined;
let [foo7] = null;
let [foo8] = {};
Set结构也可以使用数组的解构赋值
只要具备Iterator接口,就可以采用数组形式的解构赋值
let [x,y,z] = new Set(['a','a','c']);
console.log(x); // a
console.log(y); // c
console.log(z); //undefined
默认值
解构赋值允许指定默认值
let [defaultA = 'true',defaultB] = [,'a'];
console.log(defaultA,defaultB); //true,a
只有当所赋值为严格意义上的undefined时,默认值才会生效
let [defaultUndefined1,defaultUndefined2 = 1] = [2,null];
console.log(defaultUndefined1); // 2
console.log(defaultUndefined2); // null
默认值为一个表达式
function f() {
console.log("blabla");
}
let [expressX = f()] = [1];
console.log(expressX); // 1,函数未执行
对象的解构赋值
基本语法
let {first, second, middle, last} = {first:'莫', middle: '笑', last: '忘'};
console.log(first); //莫
console.log(middle); //笑
console.log(last); //忘
console.log(second); //undefined
对象的属性名无次序,没有对应属性名可匹配,则赋值为undefined;
如果变量名与属性名不一致,形式如下:
let {first: firstName} = {first:'莫'};
console.log(firstName); //莫
console.log(first); //报错
在以上解构赋值代码中,first为匹配的模式,firstName才是要被赋值的变量;
嵌套对象的解构赋值:
let obj = {
p: [
'Hello',
{
y: 'World'
}
]
};
let {
p: [x, {
y
}]
} = obj;
console.log(x); // hello
console.log(y); //world
如果希望p也作为变量赋值:
let { p, p: [x, { y }] } = obj;
如果解构模式是嵌套的对象,而且自对象的父属性不存在,会报错
let {name: {first}} = {gender: 'female'}; //报错
对象的解构赋值可以取到继承的属性;可以指定默认值,生效的条件为对象的属性值严格等于undefined;
如果将一个已经声明的变量用于结构赋值,需注意:
// 错误的写法
let x;
{x} = {x: 1};
原因:js引擎将{x}理解成一个代码块,所以发生语法错误,所以不将{}防砸行首:
let x;
({x} = {x: 1});
解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式,虽毫无意义,但是合法。也可以对数组进行对象属性的解构:
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
字符串的解构赋值
字符串被转换成了一个类似数组的对象
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值:
let {length : len} = 'hello';
len // 5
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象:
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错:
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
函数参数的解构赋值
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
圆括号问题
ES6 的规则是,只要有可能导致解构的歧义,就不得使用圆括号。
建议只要有可能,就不要在模式中放置圆括号。
不能使用圆括号的情况
变量声明语句
变量声明语句,模式不能使用圆括号
// 全部报错
let [(a)] = [1];
let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};
let { o: ({ p: p }) } = { o: { p: 2 } };
函数参数
函数参数也属于变量声明,因此不能带有圆括号
// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }
赋值语句的模式
// 全部报错
({ p: a }) = { p: 42 };
([a]) = [5];
[({ p: a }), { x: c }] = [{}, {}];
可以使用圆括号的情况
赋值语句的非模式部分,可以使用圆括号
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确
以上特征1:赋值语句;2:圆括号不属于模式的一部分
用途
交换变量的值
简便直观
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x); //2
console.log(y); //1
从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
函数参数的定义
我怎么觉得这个用途没甚意义呢
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
提取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]
函数参数的默认值
可以避免在函数体内再对参数进行默认赋值等
function ({a=1,b=2} = {}){
//BLABLA
}
遍历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) {
// ...
}
输入模块的指定方法
加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰
(这个好像很少用啊,像我现在是这样)
const { SourceMapConsumer, SourceNode } = require("source-map");