# 3. 变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

# 数组结构赋值

如果是数组,两边都需要是数组,否则会报错。

// 1. 如果是数组,两边都需要是数组,否则会报错。
//    允许嵌套,但需要格式一样。未对应的直接是undefined
let [a, b, c] = [1, 2, 3]

let [x, , y] = [1, 2, 3]
let [head, ...tail] = [1, 2, 3, 4, 5]
head // 1
tail // [2, 3, 4]

// 2. 带默认值得赋值解构, 默认值时,当对应的值 === undefined 才能使用默认值
let [foo = true] = []
foo // true

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

// 3. 默认值为函数时,函数的执行问题
function f() {
    console.log('aaa')
}
let [x = f()] = [1]
// 不会打印aaa

//  4.暂存性死区问题
let [x = y, y = 1] = [];     // ReferenceError: y is not defined

# 对象结构赋值

// 例一
let { log, sin, cos } = Math;

// 例二
const { log } = console;
log('hello') // hello


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

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

var {x = 3} = {}
x // 3

var {x, y = 5} = {x: 1}
x // 1
y // 5

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

// 特殊情况1 
var {x: y = 3} = {}
y // 3
x // Uncaught ReferenceError: x is not defined

var {x: y = 3} = {x:5}
y // 5
x // Uncaught ReferenceError: x is not defined

// 特殊情况2 对数组进行对象的解构赋值
let arr = [1, 2, 3]
let {0: first, [arr.length -1]: last} = arr
first // 1
last // 3


// 注意点:如果要将一个已经声明的变量用于解构赋值,必须非常小心。
// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

// 正确的写法
let x;
({x} = {x: 1});

# 字符串、数组、布尔值的结构赋值

const [a, b, c, d, e] = "hello"
a // "h"
c // "l"

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

// 数值和布尔值的解构赋值 特殊情况
// 如果右边是数值和布尔值,则会先转为对象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true

// 上面代码中,数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。

# 函数参数的解构赋值

function add([x, y]){
  return x + y;
}
add([1, 2]); // 3


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


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, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]

# 具体用途

// 1. 从函数返回多个值
function foo() {
    return [1, 2, 3]
}
function foo2 () {
    return {a: 1, b: 2}
}
let [x, y, z] = foo()
let {a, b} = foo2()

// 2. 提取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]

// 3.遍历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


// 4.加载模指定方法
const { SourceMapConsumer, SourceNode } = require("source-map");

// 5.函数的默认值
jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
} = {}) {
  // ... do stuff
};

// 6. 比较经典的问题,不使用额外的变量,互换两个变量的值
let a = 1, 
    b = 2;
[a, b] = [b, a] // ES6解构赋值的妙用 => [a,b] = [2,1]  => a = 2; b = 1
上次更新: 2020/10/28 下午6:32:03