解构赋值
// 对象解构
let node = {
type: "Indentifier",
name: "foo",
zs: '2'
};
let {type,name} = node;
console.log(type);
console.log(name);
//
let node ={
name: 'zs',
age: 18
}
let{name: N,age: A} = node
console.log(N);
console.log(A)
//复杂
let node = {
type: 'Identifier',
name: 'foo',
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 4
}
}
};
let {loc: {start}} = node;
console.log(start.line);
console.log(start.column);
let node = {
type: 'Identifier',
name: 'foo',
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 4
}
}
};
let {loc: {start:localStart}} = node;
console.log(localStart.line);
console.log(localStart.column);
// 数组解构
let colors = ['red','green','blue'];
let [firstColor,secondColor] = colors;
console.log(firstColor);
console.log(secondColor);
//互换值
// es5
let a = 1,
b = 2,
tmp;
tmp = a;
a = b;
b = tmp;
console.log(a); //2
console.log(b); // 1
// es6
let a = 1,
b = 2;
[a, b] = [b, a];
console.log(a); //2
console.log(b); //1
let node ={
type: 'Identifier',
name: 'foo'
}
let {type,name} = node;
console.log(type);
console.log(name);
当你使用解构赋值语句时,如果所指定的本地变量在对象中没有找到同名属性,那么该变量 会被赋值为 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",
name: "foo"
};
let {
type: localType,
name: localName
} = node;
console.log(localType); // "Identifier"
console.log(localName); // "foo"
嵌套的对象解构
let node = {
type: "Identifier",
name: "foo",
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 4
}
}
};
let {
loc: { start }
} = node;
console.log(start.line); // 1
console.log(start.column); // 1
本例中的解构模式使用了花括号,表示应当下行到 node 对象的 loc 属性内部去寻找 start 属性。每当有一个冒号在解构模式中出现,就意味着冒号之前 的标识符代表需要检查的位置,而冒号右侧则是赋值的目标。当冒号右侧存在花括号时,表 示目标被嵌套在对象的更深一层中。
数组解构
数组解构的语法看起来与对象解构非常相似,只是将对象字面量替换成了数组字面量。数组 解构时,解构作用在数组内部的位置上,而不是作用在对象的具名属性上,例如:
let colors = ["red", "green", "blue"];
let [firstColor, secondColor] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
let colors = ["red", "green", "blue"];
let [, , thirdColor] = colors;
console.log(thirdColor); // "blue"
你可以在赋值表达式中使用数组解构,但是与对象解构不同,不必将表达式包含在圆括号 内,例如:
let colors = ["red", "green", "blue"],
firstColor = "black",
secondColor = "purple";
[firstColor, secondColor] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
数组解构赋值有一个非常独特的用例,能轻易地互换两个变量的值。互换变量值在排序算法 中十分常用,而在 ES5 中需要使用第三个变量作为临时变量,正如下例:
let a = 1, b = 2, tmp;
tmp = a; a = b;
b = tmp; console.log(a); // 2
console.log(b); // 1
// 在 ES6 中互换值
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1
数组解构赋值同样允许在数组任意位置指定默认值。当指定位置的项不存在、或其值为 undefined ,那么该默认值就会被使用。例如:
let colors = ["red"];
let [firstColor, secondColor = "green"] = colors;
// 可以不加let [firstColor, secondColor = "green"] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
与解构嵌套的对象相似,可以用类似的方式来解构嵌套的数组。在整个解构模式中插入另一 个数组模式,解构操作就会下行到嵌套的数组中,就像这样:
let colors = ["red", ["green", "lightgreen"], "blue"];
// 随后
let [firstColor, [secondColor]] = colors;
console.log(firstColor); // "red"
console.log(secondColor); // "green"
剩余项
使用 … 语法来将剩余的项目赋值给一个指定的变量,此处有个范例:
let colors = ["red", "green", "blue"];
let [firstColor, ...restColors] = colors;
console.log(firstColor); // "red"
console.log(restColors.length); // 2
console.log(restColors[0]); // "green"
console.log(restColors[1]); // "blue"
在 ES5 中开发者往往使用的是一个简单的 方式,也就是用 concat() 方法来克隆数组,
var colors = ["red", "green", "blue"];
var clonedColors = colors.concat();
console.log(clonedColors); //"[red,green,blue]"
而在 ES6 中,你可以使用剩余项的语法来达到同样效果。实现如下:
// 在 ES6 中克隆数组
let colors = ["red", "green", "blue"];
let [...clonedColors] = colors;
console.log(clonedColors); //"[red,green,blue]"
混合解构
对象与数组解构能被用在一起,以创建更复杂的解构表达式。在对象与数组混合而成的结构 中,这么做便能准确提取其中你想要的信息片段。例如:
let node = {
type: "Identifier",
name: "foo",
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: 4
}
},
range: [0, 3]
};
let {
loc: { start },
range: [startIndex]
} = node;
console.log(start.line); // 1
console.log(start.column); // 1
console.log(startIndex); // 0
此代码将 node.loc.start 与 node.range[0] 提取出来,并将它们的值分别存储到 start 与 startIndex 中。要记住解构模式中的 loc: 与 range: 只是对应于 node 对象中属性的位 置。混合使用对象与数组解构, node 的任何部分都能提取出来。对于从 JOSN 配置结构中 抽取数据来说,这种方法尤其有用,因为它不需要探索整个结构。
参数解构
解构还有一个特别有用的场景,即在传递函数参数时。当 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
});
很多 JS 的库都包含了类似于此例的 setCookie() 函数。在此函数内, name 与 value 参 数是必需的,而 secure 、 path 、 domain 与 expires 则不是。并且因为此处对于其余 数据并没有顺序要求,将它们作为 options 对象的具名属性会更有效率,而无须列出一堆额 外的具名参数。这种方法很有用,但无法仅通过查看函数定义就判断出函数所期望的输入, 你必须阅读函数体的代码。
参数解构提供了更清楚地标明函数期望输入的替代方案。它使用对象或数组解构的模式替代 了具名参数。要看到其实际效果,请查看下例中重写版本的 setCookie() 函数:
function setCookie(name, value, { secure, path, domain, expires }) {
// 设置 cookie 的代码
}
setCookie("type", "js", {
secure: true,
expires: 60000
});
此函数的行为类似上例,但此时第三个参数使用了解构来抽取必要的数据。现在对于 setCookie() 函数的使用者来说,解构参数之外的参数明显是必需的;而可选项目存在于额 外的参数组中,这同样是非常明确的;同时,若使用了第三个参数,其中应当包含什么值当 然也是极其明确的。解构参数在没有传递值的情况下类似于常规参数,它们会被设为 undefined 。
参数解构的默认值