Skip to content
On this page

理解对象

难度:⭐️⭐️⭐️

💌 Object 是我们最常用的数据结构,但它的内容很多,所以还是容易对它的某些属性不太了解。

对象的每个属性或方法都由一个名称来标识,这个名称映射到一个值。因此可以把 ECMAScript 的对象想象成一张散列表,其中的内容就是一组名/值对,值可以是数据或者函数。

属性的类型

属性分两种:数据属性访问器属性

ECMA-262 使用一些内部特性来描述属性的特征。这些特性是由为 JavaScript 实现引擎的规范定义的。因此,开发者不能在 JavaScript 中直接访问这些特性

数据属性

数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。

数据属性有 4 个特性描述它们的行为:

  1. [[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。默认为 true
  2. [[Enumerable]]:表示属性是否可以通过 for-in 循环返回。默认为 true
  3. [[Writable]]:表示属性的值是否可以被修改。默认为 true
  4. [[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 个特性描述它们的行为:

  1. [[Configurable]]
  2. [[Enumerable]]
  3. [[Get]]:获取函数,在读取属性时调用。默认为 undefined
  4. [[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}`);
  }
};