欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js ES6之解构赋值

程序员文章站 2022-07-02 10:30:10
...

目录

解构赋值

1、数组的解构赋值

(1)、基本的数组解构赋值

(2)、 嵌套的数组解构赋值

(3)、带默认值的数组解构赋值

 (4)、数组的剩余运算解构赋值

(5)、Set 结构使用数组的解构赋值

(6)、不完全的数组解构赋值

(7)、失败的数组解构赋值 

2、对象的解构赋值

(1)、基本的对象解构赋值

(2)、嵌套对象解构赋值

(3)、带默认值的对象解构赋值

(4)、对象的剩余运算解构赋值

(5)、不完全的对象解构赋值

(6)、失败的对象解构赋值

(7)、对象解构赋值独有的报错

3、字符串的解构赋值

 4、数值和布尔值的解构赋值

5、函数参数的解构赋值

(1)、函数的参数的解构赋值

(2)、带默认值的函数参数的解构赋值

6、圆括号与解构赋值

7、解构赋值的用途

(1)、交换变量的值

(2)、从函数返回多个值

(3)、函数参数的定义

(4)、提取 JSON 数据

(5)、函数参数的默认值

(6)、遍历 Map 结构

 (7)、输入模块的指定方法


解构赋值

解构赋值,是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。

解构的目标:只要是可迭代对象(即实现了 Iterator 接口的数据),就可进行解构赋值

对于不可迭代的结构,解构赋值时会报错:

// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

1、数组的解构赋值

(1)、基本的数组解构赋值

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

从数组中提取值,按照对应位置,对变量赋值。

(2)、 嵌套的数组解构赋值

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

(3)、带默认值的数组解构赋值

默认值生效的条件是,数组的属性值严格等于 undefined。

let [m=3] = [];
m // 3

let [a=5, b=7] = [1];
a // 1
b // 7

let [x, y = 7] = [1, undefined]; 
x // 1
y // 7

 (4)、数组的剩余运算解构赋值

let [a, ...b] = [1, 2, 3];
a // 1
b // [2, 3]

(5)、Set 结构使用数组的解构赋值

// Set 结构可以使用数组的解构赋值
let [x, y, z] = new Set(['a', 'b', 'c']);
x // 'a'
y // 'b'
z // 'c'

(6)、不完全的数组解构赋值

/**
 * 变量不完全
 */
let [x, , z] = [1, 2, 3];
x // 1
z // 3

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

/**
 * 值不完全
 */
let [a, b=2, c] = [1]; 
a // 1
b // 2
c // undefined

(7)、失败的数组解构赋值 

如果解构失败,变量的值等于 undefined。

let [c, d] = [];
c // undefined
d // undefined

2、对象的解构赋值

(1)、基本的对象解构赋值

对象的解构与数组有一个重要的不同:

  • 数组的元素是按次序排列的,变量的取值由它的位置决定;
  • 而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
// 原本的对象解构赋值
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

// 可以简写为这样
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

// 没有次序,但是变量必须与属性同名
let { foo, bar } = { bar: 'bbb', foo: 'aaa' };
foo // "aaa"
bar // "bbb"

// 如果变量名与属性名不一致,必须写成下面这样
let { foo: baz } = { foo: 'aaa' };
baz // "aaa"

(2)、嵌套对象解构赋值

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

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

(3)、带默认值的对象解构赋值

默认值生效的条件是,对象的属性值严格等于 undefined。

var {a = 3} = {};
a // 3

let {a = 10, b = 5} = {a: 3};
// a = 3; b = 5;

let {a: aa = 10, b: bb = 5} = {a: 3};
// aa = 3; bb = 5;

var {x: y = 3} = {};
y // 3

var {x: y = 3} = {x: 5};
y // 5

var {x = 3} = {x: undefined};
x // 3

(4)、对象的剩余运算解构赋值

let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40};
// a = 10
// b = 20
// rest = {c: 30, d: 40}

(5)、不完全的对象解构赋值

let obj = {p: [{y: 'world'}] };
let {p: [{ y }, x ] } = obj;
// x = undefined
// y = 'world'

(6)、失败的对象解构赋值

如果解构失败,变量的值等于 undefined。

let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined

(7)、对象解构赋值独有的报错

①、子对象所在的父属性不存在时会报错

let {foo: {bar}} = {baz: 'baz'};
// TypeError: Cannot read property 'bar' of undefined

②、将大括号写在行首的写法会报错

let x;
{x} = {x: 1};// 报错 SyntaxError: Unexpected token '='
({x} = {x: 1});// 不报错

将大括号写在行首的写法会报错,因为 JavaScript 引擎会将 {x} 理解成一个代码块,从而发生语法错误。怎么解决呢?

将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。关于圆括号的知识请参见下文。

3、字符串的解构赋值

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

let [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

类似数组的对象都有一个 length 属性,因此还可以对这个属性解构赋值。

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

 4、数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

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

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

5、函数参数的解构赋值

(1)、函数的参数的解构赋值

[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]

(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]

undefined 就会触发函数参数的默认值。

[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]

6、圆括号与解构赋值

ES6 的规则是:只要有可能导致解构的歧义,就不得使用圆括号

但是,这条规则实际上不那么容易辨别,处理起来相当麻烦。因此,尽量不要在模式中放置圆括号

能使用圆括号的情况只有一种:

  • 赋值语句的非模式部分,可以使用圆括号。
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

7、解构赋值的用途

  • 交换变量的值
  • 从函数返回多个值
  • 函数参数的定义
  • 提取 JSON 数据
  • 函数参数的默认值
  • 遍历 Map 结构
  • 输入模块的指定方法

(1)、交换变量的值

let x = 1;
let y = 2;

[x, y] = [y, x];

(2)、从函数返回多个值

// 返回一个数组
function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象
function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

(3)、函数参数的定义

// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

(4)、提取 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)、函数参数的默认值

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]

(6)、遍历 Map 结构

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");
相关标签: # JavaScript # ES6