解构
解构赋值的作用
解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性赋给各种变量。
对象的解构
在赋值语句的左侧使用了对象字面量,即key
let node = {
type: "Identifier",
name: "foo"
};
let { type, name } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
对象的解构赋值
let node = {
type: "Identifier",
name: "foo"
},
type = "Literal",
name = 5;
// 使用解构来分配不同的值 必须用圆括号包裹解构赋值语句
({ type, name } = node);
console.log(type); // "Identifier"
console.log(name); // "foo"
注意:对象的解构赋值若没有没var/let/const声明则要使用小括号括起来,因为JavaScript语法通知解析引擎将任何以{开始的语句解析为一个块语句(例如,{console}是一个合法块语句)。而数组的解构赋值就不需要用小括号括起来。
默认值
在对象中没有找到同名属性,那么该变量会被赋值为 undefined
let node = {
type: "Identifier",
name: "foo"
};
let { type, name, value } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // undefined
可以选择性地定义一个默认值,以便在指定属性不存在时使用该值
let node = {
type: "Identifier",
name: "foo"
};
let { type, name, value = true } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // true
赋值给不同的本地变量名
let node = {
type: "Identifier"
};
let { type: localType, name: localName="bar" } = node;
console.log(localType); // "Identifier"
console.log(localName); // "bar"
每当有一个冒号在解构模式中出现,就意味着冒号左边的标识符代表需要检查的位置,而冒号右侧则是赋值的目标
对象嵌套的解构
let node = {
type: "Identifier",
name: "foo",
loc: {
start: {
line: 1,
column: 1
}
}
};
let {loc: {start}} = node;
console.log(start) // {line: 1, column: 1}
数组的解构
数组的解构和对象的解构很相似
let colors = [ "red", "green", "blue" ];
let [ color1, color2 ] = colors;
console.log(color1); // "red"
console.log(color2); // "green"
也可以在解构模式中忽略一些项,并且只给需要获取的项提供变量名
let colors = [ "red", "green", "blue" ];
let [ , , color3 ] = colors;
console.log(color3); // "blue"
color3之前的逗号,是为数组前面的项提供占位符。使用这种方法,你就可以轻易从数组任意位置取出值,而无须给其他项提供变量名。
数组的解构赋值
let colors = [ "red", "green", "blue" ],
color1 = "black",
color2 = "purple";
[ color1, color2 ] = colors;
console.log(color1); // "red"
console.log(color2); // "green"
注意:这里的解构赋值没有使用小括号,而对象的解构赋值有时是需要的。
默认值
let colors = [ "red" ];
let [ firstColor, secondColor = "green" ] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green
数组嵌套的解构赋值
let colors = [ "red", [ "green", "lightgreen" ], "blue" ];
let [ color1, [ color2 ] ] = colors;
console.log(color1); // "red"
console.log(color2); // "green
let colors = [ "red", [ "green", "lightgreen" ], "blue" ];
let [ color1, color2] = colors;
console.log(color1); // "red"
console.log(color2); // ["green", "lightgreen"]
注意以上两个例子的区别
剩余项的解构赋值
let colors = [ "red", "green", "blue" ];
let [ firstColor, ...restColors ] = colors;
console.log(firstColor); // "red"
console.log(restColors); // ["green", "blue"]
console.log(restColors[0]); // "green"
混合解构赋值
let node = {
type: "Identifier",
name: "foo",
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 4
}
},
range: [0, 3]
};
let {
loc:{start},
range: arr
} = node;
console.log(start); // {line: 1, column: 1}
console.log(arr); // [0, 3]
参数解构
当 JS 的函数接收大量可选参数时,一个常用模式是创建一个 options 对象,如下代码:
// options 上的属性表示附加参数
function setCookie(name, value, options) {
options = options || {};
let secure = options.secure,
path = options.path,
domain = options.domain,
expires = options.expires;
// 设置 cookie 的代码
}
// 第三个参数映射到 options
setCookie("type", "js", {
secure: true,
expires: 60000
});
这样写有一个很不太友善的地方,就是无法仅通过查看函数定义就判断出函数所期望的输入,你必须阅读函数体的代码。
无法仅通过查看函数定义就判断出函数所期望的输入,你必须阅读函数体的代码。如下代码:
function setCookie(name, value, { secure, path, domain, expires }) {
// 设置 cookie 的代码
}
setCookie("type", "js", {
secure: true,
expires: 60000
});
解构的参数是必须的
如果你使用解构的参数定义了一个函数,并且在调用该函数时没有给该结构参数赋值,那么程序会报错。为了解决这个问题,通常在函数声明时给给该解构参数赋值空对象。就像下面的代码。
function setCookie(name, value, { secure, path, domain, expires } = {}) {
// ...
}
参数解构的默认值
function setCookie(name, value, {
secure = false,
path = "/",
domain = "example.com",
expires = new Date(Date.now() + 360000000)
} = {}) {
// ...
}
此代码中参数解构给每个属性都提供了默认值,所以你可以避免检查指定属性是否已被传入(以便在未传入时使用正确的值)。而整个解构的参数同样有一个默认值,即一个空对象,令该参数成为可选参数。