理解对象
难度:⭐️⭐️⭐️
💌 Object 是我们最常用的数据结构,但它的内容很多,所以还是容易对它的某些属性不太了解。
对象的每个属性或方法都由一个名称来标识,这个名称映射到一个值。因此可以把 ECMAScript 的对象想象成一张散列表,其中的内容就是一组名/值对,值可以是数据或者函数。
属性的类型
属性分两种:数据属性和访问器属性。
ECMA-262 使用一些内部特性来描述属性的特征。这些特性是由为 JavaScript 实现引擎的规范定义的。因此,开发者不能在 JavaScript 中直接访问这些特性。
数据属性
数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。
数据属性有 4 个特性描述它们的行为:
[[Configurable]]
:表示属性是否可以通过delete
删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认为true
[[Enumerable]]
:表示属性是否可以通过for-in
循环返回。默认为true
[[Writable]]
:表示属性的值是否可以被修改。默认为true
[[Value]]
:包含属性实际的值。这就是前面提到的那个读取和写入属性值的位置。默认为undefined
要修改属性的默认特性,就必须使用 Object.defineProperty()
方法:
js
let person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
console.log(person.name); // "Nicholas"
person.name = "Greg";
console.log(person.name); // "Nicholas"(修改失效)
由 [[Configurable]]
属性的定义可以得知,虽然可以对同一个属性多次调用 Object.defineProperty()
,但在把 configurable
设置为 false
之后就会受限制了。
访问器属性
访问器属性不包含数据值。相反,它们包含一个获取(getter
)函数和一个设置(setter
)函数,不过这两个函数不是必需的。
访问器属性有 4 个特性描述它们的行为:
[[Configurable]]
[[Enumerable]]
[[Get]]
:获取函数,在读取属性时调用。默认为undefined
。[[Set]]
:设置函数,在写入属性时调用。默认为undefined
。
读取属性的特性
✨ 使用 Object.getOwnPropertyDescriptor()
方法可以取得指定属性的属性描述符。
js
let person = { age: 21 }
Object.defineProperty(person, 'name', {
value: 'Nicholas',
})
console.log('person', person) //person { age: 21 }(无法直接获取到[name])
console.log(Object.getOwnPropertyDescriptor(person, 'name'))
//{
// value: 'Nicholas',
// writable: false,
// enumerable: false,
// configurable: false
// }
合并对象
Object.assign()
js
/**
* 多个源对象
*/
dest = {};
result = Object.assign(dest, { a: 'foo' }, { b: 'bar' });
console.log(result); // { a: foo, b: bar }
Object.assign()
对每个源对象执行的是浅复制。
增强的对象语法
ECMAScript 6 为定义和操作对象新增了很多极其有用的语法糖特性。这些特性都没有改变现有引擎的行为,但极大地提升了处理对象的方便程度。
- 属性值简写
js
let person = {
name: name
};
// 等价于
let person = {
name
};
- 可计算属性
js
const nameKey = 'name';
const ageKey = 'age';
const jobKey = 'job';
let person = {
[nameKey]: 'Matt',
[ageKey]: 27,
[jobKey]: 'Software engineer'
};
console.log(person); // { name: 'Matt', age: 27, job: 'Software engineer' }
中括号包围的对象属性键告诉运行时将其作为 JavaScript 表达式而不是字符串来求值
- 简写方法名
js
let person = {
sayName: function(name) {
console.log(`My name is ${name}`);
}
};
// 等价于
let person = {
sayName(name) {
console.log(`My name is ${name}`);
}
};