JavaScript 对象创建
JavaScript 作为一门多功能的编程语言,允许我们在代码中模拟复杂的现实世界实体。
虽然我们已经学习了基本的数据类型(如数字、字符串和布尔值),甚至是像数组这样的集合,但在表示具有多个不同特征和行为的事物时,仅靠这些往往是不够的。
这就是 对象 (Objects) 派上用场的地方。对象是基本的构建块,允许我们将相关的数据和功能组合成一个单一的、紧密联系的单元,就像现实世界中的物品拥有特定的属性和它可以执行的动作一样。
理解如何创建这些对象、定义它们的属性 (Properties) 以及分配行为 (Methods,即方法),对于编写更有条理、更强大且更易读的 JavaScript 代码至关重要。
1. 理解对象:属性与方法
在 JavaScript 中,对象是一个独立的实体,拥有属性和类型。你可以把对象想象成一个容器,它容纳着与同一个概念相关的各种信息片段和特定动作。
这个概念可以是一个人、一辆车、一本书,甚至是一个应用程序的配置设置。
2. 使用对象字面量创建对象
在 JavaScript 中创建对象最常用、最直接的方法是使用 对象字面量 (Object Literal)。对象字面量是被花括号 {} 包围的一组逗号分隔的“名称-值”对(即属性)。
当你使用 const 或 let 声明一个对象时,你本质上是在内存中创建了对该对象的一个引用。
// 一个代表“人”的基本对象字面量
const person = {
// 属性写在这里
};
// 一个代表“产品”的基本对象字面量
let product = {
// 属性写在这里
};这种语法简单、直接,被广泛用于创建单个对象实例。
3. 定义属性 (Properties)
属性 是对象的特征或特性。它们是“键-值”对,其中 键 (Key)(也称为属性名)通常是一个描述该数据的字符串,而 值 (Value) 是实际的数据。
值可以是我们要介绍过的任何 JavaScript 数据类型:数字、字符串、布尔值、数组,甚至是另一个对象!
3.1 属性的语法
propertyName: valuepropertyName(属性名)通常是一个标识符(如 firstName, age),但如果它包含空格或特殊字符,则必须用引号括起来(例如 "first name")。为了简单和符合最佳实践,通常建议使用不带空格或特殊字符的标识符友好型名称。
3.2 带有属性的对象示例
让我们想象一下,我们想表示一个学生。一个学生有一个名字、一个 ID、一个成绩,也许还有一个他们注册课程的列表。
const student = {
firstName: "Alice", // 字符串属性
lastName: "Smith", // 字符串属性
studentId: 101, // 数字属性
isEnrolled: true, // 布尔值属性
grade: 92.5, // 数字属性
courses: ["数学", "科学", "历史"], // 数组属性
address: { // 对象属性 (嵌套对象)
street: "主街 123 号",
city: "任意城",
zipCode: "12345"
}
};
console.log(student);
/*
输出:
{
firstName: 'Alice',
lastName: 'Smith',
studentId: 101,
isEnrolled: true,
grade: 92.5,
courses: [ '数学', '科学', '历史' ],
address: { street: '主街 123 号', city: '任意城', zipCode: '12345' }
}
*/在这个 student 对象中:
firstName、lastName、studentId、isEnrolled、grade和courses都是属性。- 它们的值是不同的数据类型(字符串、数字、布尔值、数组)。
address也是一个属性,但它的值是 另一个对象。这演示了对象如何嵌套以表示更复杂的关系。
另一个例子:表示图书馆里的一本 书。
const book = {
title: "JavaScript 奇遇记",
author: "J.S. Developer",
publicationYear: 2023,
pageCount: 450,
isAvailable: true,
genres: ["编程", "教育"]
};
console.log(book);
/*
输出:
{
title: 'JavaScript 奇遇记',
author: 'J.S. Developer',
publicationYear: 2023,
pageCount: 450,
isAvailable: true,
genres: [ '编程', '教育' ]
}
*/在这里,title、author、publicationYear、pageCount、isAvailable 和 genres 都是定义 book 对象不同方面的属性。
4. 定义方法 (Methods)
如果说属性描述了一个对象是什么,那么方法则描述了一个对象能做什么。
方法 仅仅是存储为对象属性的函数。就像普通函数(第 5 模块)一样,方法可以执行动作、接收参数并返回值。关键的区别在于它们与一个对象内在通过关联。
4.1 方法的语法
你可以使用函数表达式作为属性值来定义方法:
methodName: function(parameters) {
// 方法体
}或者,使用更现代、更简洁的方法语法(ES6+),这通常是首选:
methodName(parameters) {
// 方法体
}4.2 带有方法的对象示例
让我们增强我们的 student 对象,添加一个让他们自我介绍的方法。
const student = {
firstName: "Alice",
lastName: "Smith",
studentId: 101,
isEnrolled: true,
grade: 92.5,
courses: ["数学", "科学", "历史"],
// 一个让学生自我介绍的方法
introduce: function() {
console.log("你好,我的名字是 " + this.firstName + " " + this.lastName + "。");
// 注意:`this` 关键字将在后面的课程中详细解释。
// 现在,你只需要理解 `this.firstName` 指的是 *这个* 对象的 `firstName` 属性。
}
};
// 要调用方法,使用点符号后跟括号
student.introduce(); // 输出: 你好,我的名字是 Alice Smith。在这个例子中,introduce 是 student 对象的一个方法。当被调用时,它使用对象自己的属性执行一个动作(向控制台打印一条消息)。
让我们再看一个例子,一个执行算术运算的 计算器 (calculator) 对象。
const calculator = {
// 属性 (可选,但可以用来存储状态,例如当前结果)
currentResult: 0,
// 两个数相加的方法
add: function(num1, num2) {
this.currentResult = num1 + num2;
console.log("加法结果: " + this.currentResult);
return this.currentResult;
},
// 两个数相减的方法 (使用简洁方法语法)
subtract(num1, num2) {
this.currentResult = num1 - num2;
console.log("减法结果: " + this.currentResult);
return this.currentResult;
},
// 两个数相乘的方法
multiply: (num1, num2) => { // 方法也可以使用箭头函数语法
// 注意:在箭头函数中使用 `this` 需要小心,我们稍后会讨论
// 这里为了演示暂且这样写,但在实际的对象方法中推荐前两种写法以确保 `this` 指向正确
console.log("乘法逻辑演示");
},
// 获取当前存储结果的方法
getResult() {
return this.currentResult;
}
};
// 调用方法
calculator.add(5, 3); // 输出: 加法结果: 8
calculator.subtract(10, 4); // 输出: 减法结果: 6
console.log("当前结果: " + calculator.getResult()); // 输出: 当前结果: 6在这里,add、subtract 和 getResult 是 calculator 对象的方法。它们封装了不同算术运算的逻辑,甚至可以与对象的内部状态(如 currentResult)进行交互。
示例中使用的 this 关键字(例如 this.firstName, this.currentResult)指的是对象本身。当一个方法被调用时,该方法内部的 this 指向“拥有”该方法的对象。这允许方法访问和修改对象的属性。我们将在未来的课程中深入探讨 this 关键字,但现在,只需知道它允许方法与其所属对象的数据进行交互即可。
5. 实战示例与演示
让我们把属性和方法结合起来,构建一个更全面的对象,代表一辆 车 (Car)。
// 定义一个包含属性和方法的 Car 对象
const myCar = {
make: "Toyota",
model: "Camry",
year: 2020,
color: "银色",
mileage: 50000,
isRunning: false, // 初始状态
// 启动汽车的方法
start: function() {
if (!this.isRunning) {
this.isRunning = true;
console.log(`${this.make} ${this.model} 现在正在运行。`);
} else {
console.log(`${this.make} ${this.model} 已经在运行了。`);
}
},
// 停止汽车的方法
stop() { // 使用简洁方法语法
if (this.isRunning) {
this.isRunning = false;
console.log(`${this.make} ${this.model} 已停止。`);
} else {
console.log(`${this.make} ${this.model} 已经是停止状态。`);
}
},
// 驾驶汽车的方法,增加里程数
drive(distance) {
if (this.isRunning) {
this.mileage += distance;
console.log(`行驶了 ${distance} 英里。总里程: ${this.mileage}`);
} else {
console.log(`无法驾驶。${this.make} ${this.model} 没有运行。`);
}
},
// 获取汽车信息的方法
getInfo: function() {
return `这是一辆 ${this.year} 年的 ${this.make} ${this.model},颜色为${this.color},里程 ${this.mileage} 英里。它当前处于${this.isRunning ? '运行' : '停止'}状态。`;
}
};
console.log("--- 初始汽车状态 ---");
console.log(myCar.getInfo());
// 输出: 这是一辆 2020 年的 Toyota Camry,颜色为银色,里程 50000 英里。它当前处于停止状态。
console.log("\n--- 启动汽车 ---");
myCar.start(); // 输出: Toyota Camry 现在正在运行。
console.log(myCar.getInfo());
// 输出: 这是一辆 2020 年的 Toyota Camry,颜色为银色,里程 50000 英里。它当前处于运行状态。
console.log("\n--- 尝试再次启动 ---");
myCar.start(); // 输出: Toyota Camry 已经在运行了。
console.log("\n--- 驾驶汽车 ---");
myCar.drive(100); // 输出: 行驶了 100 英里。总里程: 50100
myCar.drive(50); // 输出: 行驶了 50 英里。总里程: 50150
console.log(myCar.getInfo());
// 输出: 这是一辆 2020 年的 Toyota Camry,颜色为银色,里程 50150 英里。它当前处于运行状态。
console.log("\n--- 停止汽车 ---");
myCar.stop(); // 输出: Toyota Camry 已停止。
console.log(myCar.getInfo());
// 输出: 这是一辆 2020 年的 Toyota Camry,颜色为银色,里程 50150 英里。它当前处于停止状态。
console.log("\n--- 尝试驾驶已停止的汽车 ---");
myCar.drive(20); // 输出: 无法驾驶。Toyota Camry 没有运行。这个综合性的 myCar 对象完美地展示了属性(如 make, model, mileage)如何保存数据,而方法(start, stop, drive, getInfo)如何封装与该数据相关的动作和逻辑。这些方法修改了对象的属性(isRunning, mileage)并对其当前状态做出反应。