JavaScript对象

对象是JavaScript的核心概念,是一种复合数据类型,用于存储键值对集合和复杂数据结构。在JavaScript中,几乎所有的东西都是对象。

对象的概念

对象是由属性和方法组成的集合:

  • 属性:对象的特征,描述对象的状态
  • 方法:对象的行为,描述对象可以执行的操作

创建对象的方法

1. 对象字面量

使用花括号 {} 创建对象,是最常用的创建对象的方法。

// 对象字面量创建对象
const person = {
  name: 'Alice',
  age: 30,
  occupation: 'Engineer',
  greet: function() {
    console.log(`Hello, my name is ${this.name}!`);
  }
};

console.log(person.name); // Alice
person.greet(); // Hello, my name is Alice!

2. 构造函数

使用 new Object() 构造函数创建对象。

// 构造函数创建对象
const car = new Object();
car.brand = 'Toyota';
car.model = 'Camry';
car.year = 2023;
car.start = function() {
  console.log('Car started!');
};

console.log(car.brand); // Toyota
car.start(); // Car started!

3. 自定义构造函数

创建自定义构造函数来实例化多个相似的对象。

// 自定义构造函数
function Book(title, author, year) {
  this.title = title;
  this.author = author;
  this.year = year;
  this.getInfo = function() {
    return `${this.title} by ${this.author}, published in ${this.year}`;
  };
}

// 使用自定义构造函数创建对象实例
const book1 = new Book('JavaScript: The Good Parts', 'Douglas Crockford', 2008);
const book2 = new Book('Eloquent JavaScript', 'Marijn Haverbeke', 2018);

console.log(book1.getInfo()); // JavaScript: The Good Parts by Douglas Crockford, published in 2008
console.log(book2.getInfo()); // Eloquent JavaScript by Marijn Haverbeke, published in 2018

4. Object.create()方法

使用 Object.create() 方法创建对象,允许指定对象的原型。

// 使用Object.create()创建对象
const animal = {
  type: 'Unknown',
  makeSound: function() {
    console.log('Some generic sound');
  }
};

const dog = Object.create(animal);
dog.type = 'Dog';
dog.makeSound = function() {
  console.log('Woof!');
};

console.log(dog.type); // Dog
dog.makeSound(); // Woof!

访问对象属性

1. 点表示法

使用 . 访问对象属性,是最常用的方法。

const person = { name: 'Bob', age: 25 };
console.log(person.name); // Bob
console.log(person.age); // 25

2. 方括号表示法

使用 [] 访问对象属性,适用于属性名包含特殊字符或动态属性名。

const person = { 'full name': 'Charlie Brown', age: 10 };
console.log(person['full name']); // Charlie Brown

// 动态属性名
const propertyName = 'age';
console.log(person[propertyName]); // 10

修改对象

添加属性

const person = { name: 'David' };
person.age = 35;
person['occupation'] = 'Teacher';

console.log(person); // { name: 'David', age: 35, occupation: 'Teacher' }

修改属性

const person = { name: 'Eve', age: 28 };
person.age = 29;
person.name = 'Eva';

console.log(person); // { name: 'Eva', age: 29 }

删除属性

使用 delete 关键字删除对象的属性。

const person = { name: 'Frank', age: 40, occupation: 'Doctor' };
delete person.occupation;

console.log(person); // { name: 'Frank', age: 40 }

对象的属性类型

数据属性

用于存储数据值,具有以下特性:

  • value:属性的值
  • writable:是否可修改属性值
  • enumerable:是否可枚举(for...in循环中可见)
  • configurable:是否可配置(是否可删除或修改特性)

访问器属性

用于访问和修改属性,具有以下特性:

  • get:获取属性值的函数
  • set:设置属性值的函数
  • enumerable:是否可枚举
  • configurable:是否可配置
// 访问器属性示例
const person = {
  _firstName: 'Grace',
  _lastName: 'Hopper',
  
  get fullName() {
    return `${this._firstName} ${this._lastName}`;
  },
  
  set fullName(name) {
    const parts = name.split(' ');
    this._firstName = parts[0];
    this._lastName = parts[1];
  }
};

console.log(person.fullName); // Grace Hopper
person.fullName = 'Ada Lovelace';
console.log(person.fullName); // Ada Lovelace
console.log(person._firstName); // Ada

对象的遍历

1. for...in循环

遍历对象的可枚举属性(包括继承的属性)。

const person = { name: 'Henry', age: 32, occupation: 'Developer' };

for (const key in person) {
  console.log(`${key}: ${person[key]}`);
}
// name: Henry
// age: 32
// occupation: Developer

2. Object.keys()

返回对象自身的可枚举属性的数组。

const person = { name: 'Ivy', age: 27, occupation: 'Designer' };
const keys = Object.keys(person);

console.log(keys); // ['name', 'age', 'occupation']

keys.forEach(key => {
  console.log(`${key}: ${person[key]}`);
});

3. Object.values()

返回对象自身的可枚举属性值的数组。

const person = { name: 'Jack', age: 45, occupation: 'Manager' };
const values = Object.values(person);

console.log(values); // ['Jack', 45, 'Manager']

4. Object.entries()

返回对象自身的可枚举属性键值对的数组。

const person = { name: 'Kate', age: 29, occupation: 'Nurse' };
const entries = Object.entries(person);

console.log(entries); // [['name', 'Kate'], ['age', 29], ['occupation', 'Nurse']]

entries.forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});

对象的方法

Object.assign()

用于合并对象,将源对象的属性复制到目标对象。

// Object.assign()示例
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
console.log(target); // { a: 1, b: 2, c: 3 }

Object.freeze()

冻结对象,使其不能被修改(不能添加、修改或删除属性)。

// Object.freeze()示例
const frozenObject = { a: 1, b: 2 };
Object.freeze(frozenObject);

frozenObject.c = 3; // 不会生效
frozenObject.a = 10; // 不会生效
delete frozenObject.b; // 不会生效

console.log(frozenObject); // { a: 1, b: 2 }

Object.seal()

密封对象,使其不能添加或删除属性,但可以修改现有属性。

// Object.seal()示例
const sealedObject = { a: 1, b: 2 };
Object.seal(sealedObject);

sealedObject.c = 3; // 不会生效
sealedObject.a = 10; // 可以生效
delete sealedObject.b; // 不会生效

console.log(sealedObject); // { a: 10, b: 2 }

对象的继承

JavaScript使用原型链实现继承,每个对象都有一个原型对象,对象可以继承原型对象的属性和方法。

// 原型继承示例
function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound.`);
};

function Dog(name, breed) {
  Animal.call(this, name); // 调用父构造函数
  this.breed = breed;
}

// 设置Dog的原型为Animal的实例
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

// 重写speak方法
Dog.prototype.speak = function() {
  console.log(`${this.name} barks.`);
};

const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // Buddy barks.
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true

对象的最佳实践

  1. 使用对象字面量创建对象,简洁易读
  2. 使用驼峰命名法命名属性和方法
  3. 避免使用全局对象,防止命名冲突
  4. 使用Object.keys()、Object.values()和Object.entries()遍历对象
  5. 合理使用原型继承,避免不必要的属性复制
  6. 使用访问器属性封装复杂逻辑
  7. 考虑使用ES6的class语法创建对象(后续章节介绍)
« 上一篇 JavaScript Promise 下一篇 » JavaScript数组