JavaScript 中使用对象解构

Posted by cl9000 on July 09, 2020

人只有献身于社会,才能找出那短暂而有风险的生命的意义。 ——<阿尔伯特·爱因斯坦>

作者:Ashish Lahoti
译者:cl9000
来源:https://codingnconcepts.com/javascript/object-destructuring/

在本教程中,我们将通过示例学习在 JavaScript ES6 中对象解构的使用。

解构赋值是JavaScript ES6中引入的一种特殊语法,它允许我们在一条语句中从数组或对象中提取多个项,并将它们赋值给变量。

1. 基本对象解构

我们可以从一个对象中提取多个属性,并在一条语句中使用对象解构(Object Destructuring)将它们赋给变量。

对象解构的简写语法与我们将属性一个一个分配给变量的传统方法相比非常方便。

1
2
3
4
5
6
7
const person = { name: "John", company: "Google", job: "Developer" };

// let name = person.name; //Traditional Way
// let company = person.company;
// let job = person.job;

const { name, company, job } = person; //Object Destructuring

我们也可以将变量声明为内联的:

1
const { name, company, job } = { name: "John", company: "Google", job: "Developer" };

2. 未赋值的声明

我们可以在不赋值的情况下声明变量。值可以稍后使用对象解构来赋值,如下所示:

1
2
3
4
const person = { name: "John", company: "Google", job: "Developer" };
let name, company, job;

({ name, company, job } = person);

注意 (…); 使用不带声明的对象文字解构分配时,需要在赋值语句周围加上括号。

3. 变量名

默认情况下,变量名与您正在提取的对象属性名相同。我们总是可以像这样改变变量名:

1
2
3
4
5
6
const person = { name: "John", company: "Google", job: "Developer" };

const { name: foo, job: bar} = person;

console.log(foo); //"John"
console.log(bar); //"Developer"

请注意,现在我们只能使用 foobar 变量访问值。如果试图使用 nameage 变量访问值,则会得到未定义的错误。

4. 默认值

我们还可以为变量提供默认值,以防提取的对象属性未定义或不存在。

1
2
3
4
5
6
7
const person = { name: "John", company: "Google", job: "Developer", department: undefined };

const { name = "Bob", department = "NA", age = 21 } = person;

console.log(name); //"John"
console.log(department); //"NA" <- default value since 'undefined'
console.log(age); //21 <- default value since doesn't exist

我们还可以使用新的变量名称设置默认值:

1
2
3
4
5
6
7
const person = { name: "John", company: "Google", job: "Developer", department: undefined };

const { name:foo = "Bob", department:bar = "NA", age:baz = 21 } = person;

console.log(foo); //"John"
console.log(bar); //"NA"
console.log(baz); //21

5. 动态属性名称

我们还可以使用动态名称(属性名称在运行时已知)提取属性,如下所示:

1
2
3
4
5
6
const prop = "name";
const person = { name: "John", company: "Google", job: "Developer", department: undefined };

const { [prop]:foo } = person;

console.log(foo); //"John"

6. 嵌套对象解构

我们还可以执行嵌套对象解构以从更深层次的嵌套对象中提取属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const person = {
name: "John",
friends : ["Adam", "Bob", "Charlie"],
hobbies: ["Biking", "Cooking"],
location: {
country: "USA",
city: "NY"
},
};
const { name, friends, hobbies : [firstHobby, secondHobby], location: { country, city } } = person;

console.log(name); //"John"
console.log(friends); //["Adam", "Bob", "Charlie"]
console.log(firstHobby); //"Biking"
console.log(secondHobby); //"Cooking"
console.log(country); //"USA"
console.log(city); //"NY"

7. 剩余对象属性

其余操作符 ... 可用于将剩余的属性提取到新变量中,这些新变量尚未被对象解构所提取。

1
2
3
4
5
6
7
const person = {name: "John", company: "Google", job: "Developer", friends : ["Adam", "Bob", "Charlie"]};

const {name, friends, ...others} = person;

console.log(name); //"John"
console.log(friends); //["Adam", "Bob", "Charlie"]
console.log(others); //{company: "Google", job: "Developer"}

8. Rest 和 Spread 运算符

我们经常会混淆 RestSpread 运算符,因为它们都使用相同的 ... 语法。RestSpread 运算符可以在 Object Destructuring 语句中一起使用:

  • Rest 操作符: 用于语句的 左边,用于从对象获取剩余属性
  • Spread 操作符: 用于语句的 右侧,用于将属性复制到对象
1
2
3
4
5
6
7
8
9
10
const primaryDetails = {name: "John", company: "Google", job: "Developer"}
const otherDetails = {friends: ["Adam", "Bob", "Charlie"], hobbies: ["Biking", "Cooking"]};

// Rest operator // Spread Operator
const {name, company, hobbies, ...others} = {...primaryDetails, ...otherDetails};

console.log(name); //"John"
console.log(company); //"Google"
console.log(hobbies); //["Biking", "Cooking"]
console.log(others); //{job: "Developer", friends: ["Adam", "Bob", "Charlie"]}

9. 解构返回语句

使用 object Destructuring 可以从函数返回的对象中提取数据,方法如下:

1
2
3
4
5
6
7
8
function getPersonDetails() {
return {name: "John", company: "Google", job: "Developer"};
}

const {name, ...others} = getPersonDetails();

console.log(name); //"John"
console.log(others); //{company: "Google", job: "Developer"}

10. 解构函数参数

我们甚至可以将对象传递给函数,然后使用对象解构(object Destructuring)只提取我们想要的属性,如下所示:

1
2
3
4
5
6
7
8
const person = { name: "John", company: "Google", job: "Developer" };

function getPersonDetails({name, ...others }) {
console.log(name); //"John"
console.log(others); //{company: "Google", job: "Developer"}
}

getPersonDetails(person);

我们也可以像这样为函数参数设置默认值:

1
2
3
4
5
6
7
8
const person = { name: "John", company: "Google", job: "Developer" };

function getPersonDetails({name, department = "NA" }) {
console.log(name); //"John"
console.log(department); //"NA"
}

getPersonDetails(person);

11. 常见用例

11.1. 内部for-of循环

我们可以通过以下方式在循环内部使用对象分解 for-of

1
2
3
4
5
6
7
8
9
10
const users = [{ name: "John", company: "Google", job: "Developer" }, 
{ name: "Adam", company: "Microsoft", job: "Analyst" },
{ name: "Bob", company: "Yahoo", job: "Data Scientist" }];

for (let {name, company} of users) {
console.log(name, company);
}
// John Google
// Adam Microsoft
// Bob Yahoo

11.2. 内部map功能

我们可以通过以下方式在函数内部使用对象解构 map

1
2
3
4
5
6
7
8
const users = [{ name: "John", company: "Google", job: "Developer" }, 
{ name: "Adam", company: "Microsoft", job: "Analyst" },
{ name: "Bob", company: "Yahoo", job: "Data Scientist" }];

const userNames = users.map(({ name }) => name);

console.log(userNames);
//["John", "Adam", "Bob"]

11.3. 命名导出

我们可以使用 Object Destructuringimport 关键字选择要从模块中导出的内容。如果您使用过AngularReact或任何其他JavaScript框架。您可能遇到过这样的 Named Export

1
import React, { Component } from 'React';
1
2
3
4
5
6
7
// Old way
import React from 'React';
class MyComponent extends React.Component{}

// New way
import React, { Component } from 'React';
class MyComponent extends Component{}

同样的事情也适用于我们导入的任何其他包,我们可以只选择我们想要的函数并独立地使用它们。

1
2
3
import { isEmail, isCreditCard } from 'validator';

console.log(isEmail('my@email.com')); // true

11.4. Console API

我们可以从 Console API 对象中解构函数:

1
2
3
4
5
const { log, warn, error } = console;

log('Hello World!'); // equivalent to console.log('...');
warn('Watch out!'); // console.warn('...');
error('Something went wrong!'); // console.error('...');

11.5. 交换变量

1
2
3
4
5
6
7
8
有趣的是,我们可以使用Object Destructuring交换变量

let a = "a";
let b = "b";
[b, a] = [a, b];

console.log(a); // b
console.log(b); // a

11.6. HTML元素

我们可以像这样解构*HTML8元素的属性:

1
const { value } = document.querySelector('input');

这样,从输入元素中获取 value 属性就容易得多,就像从 button 元素中获取禁用属性一样。

1
const { disabled } = document.querySelector('button');

11.7. HTML事件

让我们使用解构函数参数来处理HTML事件,如下所示:

1
<input type="text" onchange="handleChange(event)"/>

现在,我们将从事件对象中提取目标对象,然后从目标中提取 value 属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// #1
function handleChange(event) {
const { value } = event.target;
console.log(value);
}

// # 2
function handleChange({ target }) {
const { value } = target;
console.log(value);
}

// # 3
function handleChange({ target: { value } }) {
console.log(value);
}

11.8. 创建条件对象

我们还可以使用 Object Destructuring 根据条件在运行时创建对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const isEmployed = true;
const friends = ["Adam", "Bob", "Charlie"];
const hobbies = null;
const user = {
name: "John",
...(isEmployed && {
company: "Google",
job: "Developer"
}),
...(friends && {friends}),
...(hobbies && {hobbies})
};

console.log(user);
// prints {name: "John", company: "Google", job: "Developer", friends: ["Adam", "Bob", "Charlie"]}

参考

关注【公众号】,了解更多。
关注【公众号】,了解更多。
关注【公众号】,了解更多。



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!