变量的解构赋值:
数组的解构赋值:
依照肯定模式,从数组和对象中提取对象,对变量进行赋值,称为解构.
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");