变量的解构赋值:

数组的解构赋值:

依照肯定模式,从数组和对象中提取对象,对变量进行赋值,称为解构.

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

写法属于“模式匹配”:依照对应地位,对变量赋值

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

解构不胜利:变量的值就等于undefined.

let [bar,foo] = [1]foo = undefined

不齐全解构:

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

如果左边不是数组,回报错

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

set构造,也能够解构赋值

let [x,y,z] = new Set(['a','b','c'])

只有数据结构具备迭代,都能够解构赋值

默认值

let [foo = true] = []foo = truelet [x, y='b'] =['a',undefined]x= ay = b

当一个数组成员严格等于(===)undefined的时候,才采纳默认值([y= 'b'])

对象的解构赋值

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

与数组不同的是,对象没有秩序,必须于属性同名,能力取值
解构失败,变量的值为undefined

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

能够将现有对象的办法,赋值到某个变量

let {log,sin,cos} = Mathconst {log} = consolelog('math') = hello

下面代码的例一将Math对象的对数、正弦、余弦三个办法,赋值到对应的变量上
例二将console.log赋值到log变量

变量名与属性名不统一:真正被赋值的是后者,而不是前者
let {foo:baz} = {foo:'aaa',bar:'bbb'}

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

let obj = {p:["hello",{y:"world"}]}

let {p:[x,{y}]} = obj
x = 'hello'
y = "world"

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

三次解构赋值:
const node = {
loc: {

start: {  line: 1,  column: 5}

}
};

let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc // Object {start: Object}
start // Object {line: 1, column: 5}

只有line是变量,loc和start都是模式,不是变量

嵌套赋值:
let obj = {}
let arr = []
({foo:obj.prop,bar:arr[0]} = {foo:123,bar:true})

obj = {prop:123}
arr = [true]

let {foo:{bar}} = {baz:'baz'} //报错(因为foo这时等于undefined再取子属性就会报错)

对象的解构赋值能够取到继承的属性:

const obj1= {}
const obj2 = {foo:'bar'}
Object.setPrototypeof(obj1,obj2)
const {foo} = obj1
foo = 'bar'
setPrototypeof:设置一个指定的对象的原型(即外部[[Prototype]]属性到另一个对象或null

对象obj1的原型对象是obj2。
foo属性不是obj1本身的属性,而是继承自obj2的属性,解构赋值能够取到这个属性。

默认值

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

默认值失效的条件是,对象的属性值严格等于undefined
var {x = 3} = {x = undefined}
x = 3
var {x = 3} = {x = null}
x = null

属性名表达式:
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下面代码的写法会报错,因为 JavaScript 引擎会将{x}了解成一个代码块,从而产生语法错误。只有不将大括号写在行首,防止 JavaScript 将其解释为代码块,能力解决这个问题。// 正确的写法let x;({x} = {x: 1});

字符串的解构赋值

此时,字符串被转换成了一个相似数组的对象
const [a,b,c,d,e] = "hello"
a = h
b = e
c = l
d = l
e = o

相似数组都有一个length属性,能够对这个属性解构赋值
let {length : len} = 'hello';
len // 5

数值和布尔值的解构赋值

数值和布尔值的包装对象都有toString属性,因而变量s都能取到值:
let {toString:s} = 123
s === Number.prototype.toString

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

解构赋值的规定,只有等号左边的值不是数组或对象,就先转化为对象.
因为undefined和null无奈转化为对象,所以解构会报错

函数参数的解构赋值

function add([x,y]){

return x+y

}
add([1,2])

[[1,2],[3,4]].map(([a,b])=>{a+b})
map:遍历数组返回一个新数组

对象的解构赋值默认值,没有应用函数参数的默认值:

function foo({ x, y = 0 }) {    console.log(x, y)}foo({}); // undefined 0foo({ x: 0 }); // 0 0foo({ x: 1, y: 1 }); // 1 1foo(); //报错:TypeError: Cannot read property 'x' of undefined如果函数foo调用时没提供参数,变量x和y不会生成,从而报错。function foo({ x, y = 0 } = {}) {    console.log(x, y)}foo({}); // undefined 0foo({ x: 0 }); // 0 0foo({ x: 1, y: 1 }); // 1 1foo(); // undefined 0


解释

为函数参数变量x、y指定默认值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]为函数参数指定默认值{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]

用处

  • 替换变量的值
let x = 1let y = 2[x,y] = [y,x]
  • 从函数返回多个值
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,z,y]){...}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} = jsonDatanumber =  [867, 5309]
  • 函数参数的默认值
jQuery.ajax = function (url, {  async = true,  beforeSend = function () {},  cache = true,  complete = function () {},  crossDomain = false,  global = true,  // ... more config} = {}) {  // ... do stuff};
  • 遍历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
  • 输出模块的指定办法

加载模块时,往往须要指定输出哪些办法。解构赋值使得输出语句十分清晰。
const { SourceMapConsumer, SourceNode } = require("source-map");