3.对象解构

116 阅读6分钟

JavaScript中的Object​对象用于将多个值存储为复杂的数据结构。我们创建带有花括号({...}​)和一个或多个由逗号(,​)符号分隔的属性的对象。每个属性都是由冒号(:​)符号分隔的键值对。键必须是字符串或JavaScript符号类型。值可以是任何类型,包括另一个对象。

这是一个具有六个属性的对象的示例。name​键的值是string类型,它是age​和std​键的数字。subjects​键值是一个数组。parents​和address​的值是对象。

const student = {
	'name': 'John Williamson',
	'age': 9,
	'std': 3,
	'subjects': ['Maths', 'English', 'EVS'],
	'parents': {
		'father': 'Brown Williamson',
		'mother': 'Sophia',
		'email': 'john-parents@abcde.com'
	},
	'address': {
		'street': '65/2, brooklyn road',
		'city': 'Carterton',
		'country': 'New Zealand',
		'zip': 5791
	}
}

请注意:我们将在下面的各种示例中使用这个student​对象。

对象解构

我们将数据存储在对象中,以便在以后的时间点根据需要检索它。例如,如果我们想从student​对象中检索name​和city​信息的值,我们可以这样做,

const name = student.name;
const city = student.address.city;
console.log(name, city); // John Williamson Carterton

它可以工作,但需要更多的工作。首先,我们使用点(.​)表示法来访问值。我们还需要声明几个变量来相应地分配值。

我们可以使用对象解构​语法简化从JavaScript对象中的值检索。它是EcmaScript版本6(ES6)中引入的一种新语法。它有助于从对象属性中检索值并将它们分配给变量。

使用对象解构从student​对象中检索name​属性值的表达式如下,

const {name} = student;
console.log(name); // John Williamson

在表达式的左侧,我们使用对象属性键(在本例中为name​)并将其放在{}​内。它也成为保存属性值的变量名。

我们提到const​,let​关键字来定义变量范围。不需要单独的变量声明。

在表达式的右侧,我们使用实际对象来检索值。

image

那么,我们如何使用对象解构检索多个属性值呢?我们继续在表达式左侧的{}​中添加对象键。在下面的示例中,我们使用对象解构语法从student​对象中检索name​、age​和std​信息

const {name, age, std} = student;
console.log(name, age, std); // John Williamson 9 3

您是否注意到,我们已经避免在这里编写几行额外的代码?

添加具有默认值的新变量

我们已经看到,对象解构使用新语法简化了属性值检索。但它不仅限于此。我们可以在解构时添加一个全新的变量,可以选择使用默认值。在下面的示例中,student​对象中不存在meal​变量。但是我们可以将其添加到对象解构表达式中并为其添加默认值。

const {subjects, numberOfSubjects=subjects.length} = student;
console.log(numberOfSubjects); // 3

使用析构添加别名

我们可以为我们的去结构化变量指定一个别名。当有可能发生变量名冲突时,它很有用。

在下面的示例中,我们为属性指定了一个别名,std​作为standard​。

const {std: standard} = student;
console.log(standard); // 3

这里需要注意的一点。如果我们在分配别名后尝试访问std​变量,我们会得到一个ReferenceError​,说std is not defined​。因此,一旦我们创建了别名,我们就可以仅使用别名访问属性值。

image

嵌套对象解构

嵌套对象具有一个或多个属性值作为对象。我们在本文中使用的student​对象是一个嵌套对象。它有两个属性,address​和parents​对象值。

const student = {
	.....
	'parents': {
		'father': 'Brown Williamson',
		'mother': 'Sophia',
		'email': 'john-parents@abcde.com'
	},
	'address': {
		'street': '65/2, brooklyn road',
		'city': 'Carterton',
		'country': 'New Zealand',
		'zip': 5791
	}
	.....
}

到目前为止,我们已经看到了检索非对象键值的示例。我们可以深入嵌套在层次结构中,使用解构从任何深度检索任何对象键值。在下面的示例中,我们从student​对象的address​属性中检索了zip​值。

我们已经知道如何检索address​键的值,

​const {address} = student;​

如果我们在控制台中记录address​变量,这是输出,

image

但是我们对zip​值感兴趣,我们希望一步到位。让我们使用解构,

const {address : {zip}} = student;
console.log(zip); // 5791

你可以像这样进入任何深度。您需要始终从顶层开始,然后在层次结构中向下,直到达到要检索的值。



对函数参数的分解

我们可以使用对象解构编写精确而智能的代码,并将其作为函数参数传递。让我们用一个例子来理解它。通常的学生对象就像,

const student = {
	'name': 'John Williamson',
	'age': 9,
	'std': 3,
	'subjects': ['Maths', 'English', 'EVS'],
	'parents': {
		'father': 'Brown Williamson',
		'mother': 'Sophia',
		'email': 'john-parents@abcde.com'
	},
	'address': {
		'street': '65/2, brooklyn road',
		'city': 'Carterton',
		'country': 'New Zealand',
		'zip': 5791
	}
}

假设我们有一个向学生家长发送电子邮件的函数(注意,parents​属性下有一个email​属性)。此函数还记录发送成功电子邮件的语句。

所以,我们可以像这样调用函数,

​sendEmail(student);​

我们可以使用解构将email​值传递给函数定义。无需传递整个student​对象,然后在函数内部检索所需的值。

const sendEmail = ({parents: {email}}) => {
console.log(`Sent email to ${email}`);
}

请注意,我们已经在上面的函数中执行了嵌套对象解构来检索email​值。

析构函数返回值

在JavaScript中,函数可能会返回一个对象。当我们调用该函数时,我们可能对整个对象不感兴趣,而是对其特定的属性值感兴趣。这是另一个使用对象解构的机会。

在下面的示例中,函数getStudent​返回一个对象

const getStudent = () => {
	return {
		'name': 'John Williamson',
		'age': 9,
		'std': 3,
		'subjects': ['Maths', 'English', 'EVS'],
		'parents': {
			'father': 'Brown Williamson',
			'mother': 'Sophia',
			'email': 'john-parents@abcde.com'
		},
		'address': {
			'street': '65/2, brooklyn road',
			'city': 'Carterton',
			'country': 'New Zealand',
			'zip': 5791
		}
	}
}

我们只对name和subjects键值感兴趣。我们可以使用解构表达式检索它们,

const { name, subjects } = getStudent();
console.log(name, subjects);

输出,

image

环路内的破坏

当我们需要循环中的对象键值时,对象解构会派上用场。我们可以使用简单的语法将解构与for-of​循环一起使用。让我们以学生数组为例。为了简单起见,每个学生对象只有两个属性,name和grade。

const students = [
	{
	'name': 'William',
	'grade': 'A'
	},
	{
	'name': 'Tom',
	'grade': 'A+'
	},
	{
	'name': 'Bob',
	'grade': 'B'
	}
];

现在,我们将使用for-of​循环遍历学生数组并从每个students​对象中检索值。为此,我们可以使用对象解构,

for(let {name, grade} of students){
	console.log(`${name} has got the grade ${grade}`);
}

输出,

image

使用动态名称属性进行解构

在许多情况下,您可能事先不知道对象属性的键。您可能只在代码执行的运行时知道它。在这种情况下,您不能使用对象解构来硬编码键名以检索值。

例如,让我们采用一个函数getStudentInfo​,它将键作为参数并从对象返回相应的值。

getStudentInfo('name'); // Returns, John Williamson
getStudentInfo('age'); // Returns, 9

传递给函数getStudentInfo​的参数是动态的。因此,要使用带有动态键的对象解构​,我们需要用一对方括号([...]​)将键括起来。

const getStudentInfo = key => {
const {[key]: value} = student;
return value;
}

省略上述代码中的方括号将导致未定义​的值。



关于对象解构的一些提示

对象解构是JavaScript编程语言中令人兴奋的一部分。正如您到目前为止所看到的,在我们使用JavaScript的日常编程中有很多可能性。以下是一些您可能会发现有帮助的提示。

  • ​let​、const​关键字在对象解构语法中具有重要作用。在代码语法中省略它们将最终导致错误,Uncaught SyntaxError: Unexpected token '='​。

    // Don't do this
    {name} = student; // Uncaught SyntaxError: Unexpected token '='
    

    即使您提前声明了变量并尝试稍后在解构语法中使用它,也会导致类似的错误。

    let name;
    {name} = student; // Uncaught SyntaxError: Unexpected token '='
    

    如果您必须省略let​、const​关键字,则必须将解构表达式放在括号内((...)​)。

    let name;
    ({ name } = student);
    console.log(name); // John Williamson
    
  • 对象解构语法可能有点难记住。如果你最终不记得也没关系。这是通常的。你可以参考任何像这样的指南来获取语法并使用它。