春风得意马蹄疾
一日看尽长安花

深入理解ES6解构赋值:一、对象解构

我们经常定义许多对象和数组,然后有组织地从中提取相关的信息片段。在ES6中添加了可以简化这种任务的新特性:解构。解构是一种打破数据结构,将其拆分为更小部分的过程。

前言

在ES5中,开发者们为了从对象和数组中获取特定数据并赋值给变量,编写了许多看起来同质化的代码

let options = {
    repeat: true,
    save: false
};
// 从对象中提取数据
let repeat = options.repeat,
save = options.save;

这段代码从options对象中提取repeat和save的值,并将其存储为同名局部变量,提取的过程极为相似

如果要提取更多变量,则必须依次编写类似的代码来为变量赋值,如果其中还包含嵌套结构,只靠遍历是找不到真实信息的,必须要深入挖掘整个数据结构才能找到所需数据

所以ES6添加了解构功能,将数据结构打散的过程变得更加简单,可以从打散后更小的部分中获取所需信息

对象解构

对象字面量的语法形式是在一个赋值操作符左边放置一个对象字面量

let node = {
    type: "Identifier",
    name: "foo"
};
let { type, name } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"

在这段代码中,node.type的值被存储在名为type的变量中;node.name的值被存储在名为name的变量中

【解构赋值】

到目前为止,我们已经将对象解构应用到了变量的声明中。然而,我们同样可以在给变量赋值时使用解构语法

let node = {
    type: "Identifier",
    name: "foo"
},
type = "Literal",
name = 5;
// 使用解构来分配不同的值
({ type, name } = node);
console.log(type); // "Identifier"
console.log(name); // "foo"

在这个示例中,声明变量type和name时初始化了一个值,在后面几行中,通过解构赋值的方法,从node对象读取相应的值重新为这两个变量赋值

注意:【1】一定要用一对小括号包裹解构赋值语句,JS引擎将一对开放的花括号视为一个代码块。语法规定,代码块语句不允许出现在赋值语句左侧,添加小括号后可以将块语句转化为一个表达式,从而实现整个解构赋值过程

【2】解构赋值表达式(也就是=右侧的表达式)如果为null或undefined会导致程序抛出错误。也就是说,任何尝试读取null或undefined的属性的行为都会触发运行时错误

【默认值】

使用解构赋值表达式时,如果指定的局部变量名称在对象中不存在,那么这个局部变量会被赋值为undefined

let node = {
    type: "Identifier",
    name: "foo"
};
let { type, name, value } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // undefined

这段代码额外定义了一个局部变量value,然后尝试为它赋值,然而在node对象上,没有对应名称的属性值,所以像预期中的那样将它赋值为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

在此示例中,为变量value设置了默认值true,只有当node上没有该属性或者该属性值为undefined时该值才生效。此处没有node.value属性,因为value使用了预设的默认值

【为非同名局部变量赋值】

如果希望使用不同命名的局部变量来存储对象属性的值,ES6中的一个扩展语法可以满足需求,这个语法与完整的对象字面量属性初始化程序的很像

let node = {
    type: "Identifier",
    name: "foo"
};
let { type: localType, name: localName } = node;
console.log(localType); // "Identifier"
console.log(localName); // "foo"

这段代码使用了解构赋值来声明变量localType和localName,这两个变量分别包含node.type和node.name属性的值。type:localType语法的含义是读取名为type的属性并将其值存储在变量localType中,这种语法实际上与传统对象字面量的语法相悖,原来的语法名称在冒号左边,值在右边;现在值在冒号右边,而对象的属性名在左边

当使用其他变量名进行赋值时也可以添加默认值,只需在变量名后添加等号和默认值即可

let node = {
    type: "Identifier"
};
let { type: localType, name: localName = "bar" } = node;
console.log(localType); // "Identifier"
console.log(localName); // "bar"

在这段代码中,由于node.name属性不存在,变量被默认赋值为"bar"

【嵌套对象解构】

解构嵌套对象仍然与对象字面量的语法相似,可以将对象拆解以获取想要的信息

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 node = {
    type: "Identifier",
    name: "foo",
    loc: {
        start: {
            line: 1,
            column: 1
        },
        end: {
            line: 1,
            column: 4
        }
    }
};
// 提取 node.loc.start
let { loc: { start: localStart }} = node;
console.log(localStart.line); // 1
console.log(localStart.column); // 1

在这个版本中,node.loc.start被存储在了新的局部变量localStart中。解构模式可以应用于任意层级深度的对象,且每一层都具备同等的功能

下一篇:深入理解ES6解构赋值:二、数组解构

Like
Like Love Haha Wow Sad Angry
赞(0) 打赏
未经允许不得转载:栗子纪blog » 深入理解ES6解构赋值:一、对象解构
分享到: 更多 (0)
0 0 vote
Article Rating
Subscribe
提醒
guest
0 评论
Inline Feedbacks
View all comments

创作不易,打赏一下作者买瓶洗发露

支付宝扫一扫打赏

微信扫一扫打赏

0
Would love your thoughts, please comment.x
()
x