解构是一种打破数据结构,将其拆分为更小部分的过程。
解构用法
对象解构
对象解构的语法形式是再一个赋值操作符左边放置一个对象字面量。
let node = {
type: 'id',
name: 'foo'
}
let {type, name} = node;
console.log(type); // id
console.log(name); // foo
注意:如果使用var、let、const解构声明变量,则必须提供初始化程序(也就是等号右侧的值),否则会导致程序抛出语法错误↓
// 语法错误!
let {type, name};
var {type, name};
const {type, name};
解构赋值
我们同样可以在给变量赋值时使用解构语法
let node = {
type: 'id',
name: 'foo'
},
type = 'name',
name = 'id';
({type, name} = node;)
console.log(type); // id
console.log(name); // foo
注意: 一定要用一对小括号包裹解构赋值语句,Javascript引擎将一对开放的花括号是为一个代码块,而语法规定,代码块语句不允许出现在赋值语句左侧,添加小括号后可以将块语句转化为一个表达式,从而实现整个解构赋值的过程。
解构表达式的值与表达式右侧的值相等,在任何可以使用值的地方都可以使用解构赋值表达式(解构赋值表达式如果为null或undefined会导致程序抛出错误)
let node = {
type: 'id',
name: 'foo'
},
type = 'name',
name = 'id';
function outputInfo(value) {
console.log(value === node); // true
}
outputInfo({type, name} = node);
console.log(type); // id
console.log(name); // foo
默认值
使用解构赋值表达式时,如果制定的局部变量名称在对象中不存在,那么这个局部变量会被赋值为undefined。
let node = {
type: 'id',
name: 'foo'
};
let {type, name, value} = node;
console.log(type); // id
console.log(name); // foo
console.log(value); // undefined
当指定的属性不存在时,可以随意定义一个默认值,在属性名称后面加个等号和相应的默认值即可。
let node = {
type: 'id',
name: 'foo'
};
let {type, name, value = true} = node;
console.log(type); // id
console.log(name); // foo
console.log(value); // true
为非同名局部变量赋值
ES6可以使用不同命名的局部变量来存储对象属性的值,并且可以为其添加默认值。
let node = {
type: 'id',
name: 'foo'
};
let {type, name: localName, value: localValue = true} = node;
console.log(type); // id
console.log(localName); // foo
console.log(localValue); // true
嵌套对象解构
let node = {
type: 'id',
name: 'foo',
loc: {
start:{
line: 1,
column: 1
},
end: {
line: 2,
column: 2
}
}
}
let {loc: {start, end: localEnd}} = node;
console.log(start.line); // 1
console.log(start.column); // 1
console.log(localEnd.line); // 2
console.log(localEnd.column); // 2
所有冒号前的标识符都代表在对象中的检索位置,其右侧为被赋值的变量名; 如果冒号后时花括号,则意味着要赋予的最终值嵌套在对象内部更深的层级中。
数组解构
数组解构也可用于赋值上下文,但不需要用小括号包裹表达式。
let colors = ['red', 'green', 'blur'],
firstColor = 'black',
secondColor = 'pink';
[firstColor, secondColor] = colors;
[, , thirdColor] = colors;
console.log(firstColor); // red
console.log(secondColor); // green
console.log(secondColor); // blur
数组解构语法还有一个独特的用例:交换两个变量的值
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1
默认值
也可以在数组解构赋值表达式中为数组中的任意位置添加默认值,当指定位置的属性不存在或其值为undefined时使用默认值。
let colors = ['red', 'green', 'blur'],
firstColor = 'black',
secondColor = 'pink';
[firstColor, secondColor, thirdColor, fourColor = 'white'] = colors;
console.log(firstColor); // red
console.log(secondColor); // green
console.log(fourColor); // white
嵌套数组解构
在原有的数组模式中插入另一个数组模式,即可将解构过程深入到下一个层级。
let colors = ['red', ['green', 'black'], 'blur'];
let [firstColor, [secondColor]] = colors;
console.log(firstColor); // red
console.log(secondColor); // green
不定元素
在数组解构中,可以通过...语法将数组中的其余元素赋值给一个特定的变量, 不定元素必须为最后一个条目。
let colors = ['red', 'green', 'blur'];
let [firstColor, ...restColor] = colors;
console.log(firstColor); // red
console.log(restColor); // ['green', 'blur']
我们可以通过不定元素的语法来实现数组的克隆
let colors = ['red', 'green', 'blur'];
let [ ...cloneColor] = colors;
console.log(cloneColor); // ['red', 'green', 'blur']
混合解构
可以混合使用对象解构和数组解构来创建更多复杂的表达式,来从任何混杂着对象和数组的数据解构中提取信息
let node = {
type: 'id',
name: 'foo',
loc: {
start:{
line: 1,
column: 1
},
end: {
line: 2,
column: 2
}
},
range: [0, 1, 2, 3]
}
let {loc: {start}, range: [startIndex]} = node;
console.log(start.line); // 1
console.log(start.column); // 1
console.log(startIndex); // 0
解构参数
解构可以用在函数参数的传递过程中,当定义一个接受大量可选参数的Javascript函数时,我们通常会创建一个可选对象,将额外的参数定义为这个对象的属性。
// options的属性表示其他参数
function setCookie(name, vallue, options) {
options = options || {};
let secure = options.secure,
path = options.path,
domain = options.domain,
expires = options.expires;
// 业务代码
}
setCookie('type', 'js', {
secure: true,
expires: 6000
});
缺点:仅查看函数的声明部分,无法辨识函数的预期参数,必须通过阅读函数体才可以确定所有参数的情况。
改进:将options定义为解构参数,则可以更清晰地了解函数预期传入的参数。解构参数需要使用对象或数组解构模式代替命名参数
function setCookie(name, vallue, {secure, path, domain, expires}) {
// 业务代码
}
setCookie('type', 'js', {
secure: true,
expires: 6000
});
必须传值的解构参数
解构参数有一个奇怪的地方,默认情况下,如果调用函数时不提供被解构的参数会导致程序抛出错误。
// 程序报错
setCookie('type', 'js')
缺失的第三个参数,其值为undefined。Javascript引擎实际上做了这些事↓
function setCookie(name, vallue, options) {
let {secure, path, domain, expires} = options;
// 业务代码
}
如果希望将解构参数定义为可选的,就必须为其提供默认值。
function setCookie(name, vallue, {secure, path, domain, expires} = {}) {
// 业务代码
}
解构参数的默认值
可以为结构参数指定默认值。
function setCookie(name, vallue, {
secure = false,
path = '/',
domain = 'example.com',
expires = 6000}) {
// 业务代码
}
缺点:函数声明比以前复杂,其次如果解构参数是可选的,任然需要添加一个空对象作为参数。
建议:对于对象类型的解构参数,为其赋予相同解构的默认参数↓
function setCookie(name, vallue, {
secure = false,
path = '/',
domain = 'example.com',
expires = 6000} = {
secure = false,
path = '/',
domain = 'example.com',
expires = 6000}) {
// 业务代码
}
将默认值提取到一个独立对象中,并且使用该对象作为结构和默认参数的一部分,可以消除代码冗余。
const setCoolieDefault = {
secure = false,
path = '/',
domain = 'example.com',
expires = 6000
}
function setCookie(name, vallue, {
secure = setCoolieDefault.secure,
path = setCoolieDefault.path,
domain = setCoolieDefault.domain,
expires = setCoolieDefault.expires
} = setCoolieDefault) {
// 业务代码
}
优点:如果要改变默认值,只需要在setCoolieDefault中修改,修改的数据将自动同步到所有出现过的地方。