ES6学习笔记——变量的解构赋值

ES6学习笔记——变量的解构赋值

数组的解构赋值

基本用法

对称解构

只要等号两边的模式相同,左边的变量就会被赋予对应的值。

一次性给三个变量赋值:

1
2
let [a, b, c] = [1, 2, 3];
let [x, , y] = [1, 2, 3];

给多维数组赋值:

1
let [a, b, [c, d]] = [1, 2, [3, 4]];

rest:

1
2
3
let [head, ...tail] = [1, 2, 3, 4];
tail
// [2, 3, 4]

如果解构不成功则被赋值为 undefined

非对称解构

1
2
let [x, y] = [1, 2, 3];
// 也成功

如果等号的右边是不可比遍历的解构则报错。

Set

1
2
let [x, y, z] = new Set([1, 2, 3]);
// 成功

只要数据类型具有Iterator接口就可以使用数组结构。

默认值

指定默认值:

1
2
3
4
5
let [name = 'mason'] = [];
name // 'mason'

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

es6内部判断一个位置是否有值: 严格等于 undefined 才会赋予默认值,也就是说除了 undefined 不能作为默认值其他都可以。

1
2
3
4
5
let [x = 1] = [undefined];
// x = 1

let [x = 1] = [null];
// x = null

如果默认值是一个表达式,那么这个表达式不会执行并返回值,因为表达式是惰性求值的。

1
2
3
4
5
6
function f() {
return 1;
}

let [a = f()] = [2];
// a为2

对象的解构赋值

1
2
3
let {a, b} = {a:'a', b: 'b'};
// a: 'a'
// b: 'b'

对象的解构没有次序限制,变量名需要和属性名相同。

1
2
3
let {a, b} = {b: 'b', a: 'a'};
// a: 'a'
// b: 'b'

如果解构失败,变量的值为undefined

使用对象解构赋值可以动态的给变量赋值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let Math = {
log: function() {

},
sin: function() {

},
cos: function() {

},
tan: function() {

},
...
};
let {log, sin, cos} = Math;

如果变量名和属性名不一致,则要写成这样:

1
2
3
4
// 这里的aa和bb相当于a和b的别名
let {a: aa, b: bb} = {b: 'b', a: 'a'};
// aa: 'a'
// bb: 'b'

也就是说对象的解构赋值是如下机制:先找到同名属性然后赋值给对应的变量。

1
let {foo: foo, bar: bar} = {foo: 'a', bar: 'b'};

对象的解构也可以嵌套:

1
2
3
4
5
6
7
8
9
10
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};

let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"

默认值

对象的解构也可以指定默认值,具体同数组的解构一样。

默认值生效的条件是对象的属性值=== undefined

1
2
3
4
5
6
7
// 生效
let {x = 3} = {x: undefined};
// x = 3

// 不生效
let {x = 3} = {x: 1};
// x 1

注意点

  1. 如何解构一个已经声明了的变量:
1
2
let x;
({x} = {x: 1});
  1. 对于类似数组的对象也可以与数组结构
1
2
let arr = [1, 2, 3];
let {0: 'a', 1: 'b', 2: 'c'} = arr;

字符串的解构赋值

对于非对象和数组的类型在被解构时会先被转为包装对象:

1
2
3
4
let [a, b, c] = 'why';

let {length: len} = 'hello';
// len = 5

数值和布尔值的解构赋值

对于非对象和数组的类型在被解构时会先被转为包装对象:

1
2
3
4
5
let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true

undefined和null

undefinednull无法转为对象故而在结构时会报错。

函数参数的解构赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function add([x, y]) {
return x + y;
}
add([1, 2]);


function move(x = 0, y = 0) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]


function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

圆括号问题

不能使用圆括号的情况

  1. 变量声明
  2. 参数函数
  3. 赋值语句模式

可以使用圆括号的情况

  1. 赋值语句的非模式部分
1
2
3
[(a)] = [1];
({p: (d)} = {});
[{parseInt.prop}] = [3];

变量解构的用途

  1. 交换变量
1
[x, y] = [y, x];
  1. 从函数返回多个值

函数只能return一个值,想要返回多个值就要把他们放到数组或者对象里面。

1
2
3
4
5
6
7
8
// 以返回对象为例
function f() {
return {
foo: 1,
bar: 2
};
}
let {foo, bar} = f();
  1. 函数参数的定义
1
2
3
4
5
6
7
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
  1. 提取JSON
1
2
3
4
5
6
7
let data = {
name: 'wang',
age: 22,
isMarried: false
};

let {name, age, isMarried} = data;
  1. 函数参数的默认值
1
2
3
4
5
6
7
let f = function({
name = '',
age = 0,
isMarried = false,
} = {}) {
// 操作参数
}
  1. 遍历Map
1
2
3
4
5
6
7
8
9
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
1
2
3
4
5
6
7
8
9
// 获取键名
for (let [key] of map) {
// ...
}

// 获取键值
for (let [,value] of map) {
// ...
}
  1. 输入模块的指定方法
1
const { SourceMapConsumer, SourceNode } = require("source-map");

评论