JavaScript 是一门动态语言,它的对象系统非常灵活,可以随意添加、修改或删除属性。ES7 引入了不少新特性来使对象使用更方便,本文将介绍几个常见问题及对应的解决方案。
1. 对象的浅拷贝和深拷贝
假设我们有一个 person
对象:
const person = { name: '张三', age: 18 };
我们需要把它复制一份,并修改 name
属性为 '李四'
,然后输出原始的 person
对象,看看是否被修改了。我们可以使用浅拷贝和深拷贝两种方式。
1.1 浅拷贝
浅拷贝只会复制对象的一层属性,如果对象的属性值是对象的话,只会复制它的引用,不会复制属性值对象。常见的浅拷贝方法有:
1.1.1 Object.assign
Object.assign
方法用于将所有可枚举属性值从一个或多个源对象复制到目标对象。该方法的第一个参数是目标对象,后面的参数都是源对象。
const clone = Object.assign({}, person); clone.name = '李四'; console.log(person); // { name: '张三', age: 18 } console.log(clone); // { name: '李四', age: 18 }
Object.assign
拷贝的是属性值,如果源对象的属性也是一个对象,则只拷贝其引用,因此修改源对象的属性值也会影响目标对象。
const person = { name: '张三', hobbies: ['篮球', '游泳'] }; const clone = Object.assign({}, person); person.hobbies.push('跑步'); console.log(person); // { name: '张三', hobbies: [ '篮球', '游泳', '跑步' ] } console.log(clone); // { name: '张三', hobbies: [ '篮球', '游泳', '跑步' ] }
1.1.2 扩展操作符
扩展操作符(...
)用于将一个数组或对象展开为另一个数组或对象。在对象上使用扩展操作符时,可以完成浅拷贝的操作。
const clone = { ...person }; clone.name = '李四'; console.log(person); // { name: '张三', age: 18 } console.log(clone); // { name: '李四', age: 18 }
1.2 深拷贝
深拷贝会递归复制对象及其属性值,生成一个全新的对象。常见的深拷贝方法有:
1.2.1 JSON.parse 和 JSON.stringify
可以使用 JSON.parse(JSON.stringify(obj))
的方式进行深拷贝。它的原理是将对象转为 JSON 字符串,再将 JSON 字符串转为对象。由于 JSON 格式不支持所有 JavaScript 对象类型,因此只支持 JSON 类型的数据。
const clone = JSON.parse(JSON.stringify(person)); clone.name = '李四'; clone.hobbies.push('跑步'); console.log(person); // { name: '张三', hobbies: [ '篮球', '游泳' ] } console.log(clone); // { name: '李四', hobbies: [ '篮球', '游泳', '跑步' ] }
1.2.2 Lodash 的深拷贝方法
Lodash 是一个实用的 JavaScript 工具库,它提供了很多便捷的工具函数,其中有一个深拷贝方法 _.cloneDeep
可以实现深拷贝。
const clone = _.cloneDeep(person); clone.name = '李四'; clone.hobbies.push('跑步'); console.log(person); // { name: '张三', hobbies: [ '篮球', '游泳' ] } console.log(clone); // { name: '李四', hobbies: [ '篮球', '游泳', '跑步' ] }
2. 对象属性访问的简便方式
访问对象的属性通常需要使用点操作符 (.
) 或方括号 ([]
),这种方式有时会比较繁琐,ES7 引入了一些新特性让访问对象属性更方便。
2.1 属性值简写
在 ES6 中,可以使用属性值简写的方式定义对象属性。例如,下面的代码:
const name = '张三'; const age = 18; const person = { name, age };
相当于:
const name = '张三'; const age = 18; const person = { name: name, age: age };
虽然这种方式只是简写,但它确实让属性定义更简洁了。
2.2 可计算属性名
在 ES6 中,可以使用方括号定义属性名:
const person = { [name]: '张三', [age]: 18 };
其中,name
和 age
变量被定义为属性名。ES7 引入了可计算属性名,可以在对象字面量的方括号中使用表达式。
const person = { [`name_${name}`]: '张三', [`age_${age}`]: 18 };
这样就可以根据变量和表达式来定义属性名了。
2.3 可选链操作符
在使用 person.name
访问对象属性时,如果 person
为 null
或 undefined
,则会抛出 TypeError
,使程序停止运行。为了避免这种情况,需要增加一些判断逻辑。ES7 引入了可选链操作符 (?.
),可以简化这类逻辑的编写。
const nameLength = person?.name?.length;
如果 person
或 name
不存在,则直接返回 undefined
,不会抛出错误。
3. 对象的解构赋值
解构赋值可以从对象中提取属性值,赋值给变量。ES7 引入了解构赋值的新语法,可以让代码更简洁。
3.1 对象解构赋值
对象解构赋值可以从对象中提取属性值,赋值给对应的变量。
const person = { name: '张三', age: 18 }; const { name, age } = person; console.log(name); // 张三 console.log(age); // 18
在解构赋值中,变量名和对象属性名相同时,可以简写为一个标识符。
const { name, age } = person;
可以使用默认值来避免一个属性不存在的情况。
const { name, age, gender = '男' } = person; console.log(gender); // 男
可以使用别名来改变变量名。
const { name, age, gender: sex = '男' } = person; console.log(sex); // 男
3.2 嵌套对象解构赋值
如果对象属性的值还是一个对象,可以进行嵌套解构赋值。
const person = { name: '张三', age: 18, address: { country: '中国', city: '北京' } }; const { name, age, address: { city } } = person; console.log(city); // 北京
总结
本文介绍了 ES7 中对象的浅拷贝和深拷贝、属性访问的简便方式和对象的解构赋值等常见问题及解决方案。这些技巧可以让你更方便地操作对象,提高代码的可读性和可维护性。如果你有其他优秀的技巧,欢迎留言分享。
示例代码如下:
-- -------------------- ---- ------- ----- ------ - - ----- ----- ---- -- -- ----- ----- - ----------------- -------- ---------- - ----- -------------------- -- - ----- ----- ---- -- - ------------------- -- - ----- ----- ---- -- - ----- ------ - - ----- ----- -------- ------ ----- -- ----- ----- - ----------------- -------- -------------------------- -------------------- -- - ----- ----- -------- - ----- ----- ---- - - ------------------- -- - ----- ----- -------- - ----- ----- ---- - - ----- ----- - -------------------- ---------- - ----- ------------------------- -------------------- -- - ----- ----- -------- - ----- ---- - - ------------------- -- - ----- ----- -------- - ----- ----- ---- - - ----- ------ - - ----- ----- -------- ------ ----- -- ----- ----- - ----------------------------------- ---------- - ----- ------------------------- -------------------- -- - ----- ----- -------- - ----- ---- - - ------------------- -- - ----- ----- -------- - ----- ----- ---- - - ----- ---- - ----- ----- --- - --- ----- ------ - - ----- --- -- ----- ------ - - ----------------- ----- --------------- -- -- ----- ---------- - --------------------- ----- ------ - - ----- ----- ---- -- -- ----- - ----- --- - - ------- ------------------ -- -- ----------------- -- -- ----- - ----- ---- ------ - --- - - ------- -------------------- -- - ----- - ----- ---- ------- --- - --- - - ------- ----------------- -- - ----- ------ - - ----- ----- ---- --- -------- - -------- ----- ----- ---- - -- ----- - ----- ---- -------- - ---- - - - ------- ------------------ -- --
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64fbc8bff6b2d6eab31efa6a