JavaScript: JavaScript 对象
对象是 JavaScript 中最核心的数据结构。你可以把它想象成一张信息卡——正面写着"姓名:张三",背面写着"年龄:20"。每一项信息都有一个键(key)和一个值(value),合在一起就是键值对。
1. 对象的创建与操作
▶ 示例
JAVASCRIPT
// 本节代码示例
const message = "你好,世界!";
console.log(message);
这是最简单的示例,后续章节会详细解释。### (1) 对象字面量创建
用花括号 {} 直接写出对象,这是最常见的方式:
HTML
<script>
const student = {
name: "张三",
age: 20,
major: "计算机"
};
console.log(student);
</script>
键和值之间用冒号分隔,多个键值对之间用逗号分隔。最后一个键值对后面的逗号是允许的(叫尾逗号),加上反而方便后续增删。
(2) 访问属性
两种方式访问对象的属性:
| 方式 | 写法 | 适用场景 |
|---|---|---|
| 点语法 | obj.name |
属性名是合法标识符时 |
| 方括号 | obj["name"] |
属性名含特殊字符、用变量动态访问时 |
方括号的最大优势:可以用变量作为键名。
HTML
<script>
const key = "name";
console.log(student[key]); // 等价于 student["name"]
</script>
(3) 修改和添加属性
对象创建后,你可以随时修改已有属性或添加新属性——哪怕对象是用 const 声明的(const 只锁引用,不锁内容)。
HTML
<script>
student.age = 21; // 修改
student.grade = "大三"; // 添加新属性
console.log(student);
</script>
(4) 删除属性
用 delete 操作符彻底移除一个属性:
HTML
<script>
delete student.grade;
console.log(student);
</script>
删除后再次访问会得到 undefined。
(5) 方法
对象里的函数叫方法。把函数作为属性的值,对象就"会做事"了:
HTML
<script>
const dog = {
name: "旺财",
bark() {
return "汪汪!我是" + this.name;
}
};
console.log(dog.bark());
</script>
(6) this 关键字
this 指向"当前对象"——谁调用这个方法,this 就是谁。这是 JavaScript 最容易踩坑的地方之一:如果方法被单独取出来调用,this 就不再是原来的对象了。
HTML
<script>
const bark = dog.bark;
console.log(bark()); // this 不再指向 dog,可能指向 window 或 undefined
</script>
(7) 构造函数
需要批量创建同结构的对象时,用构造函数:
HTML
<script>
function Person(name, age) {
this.name = name;
this.age = age;
this.sayHi = function() {
return "你好,我是" + this.name;
};
}
const p1 = new Person("李四", 25);
const p2 = new Person("王五", 30);
console.log(p1.sayHi());
console.log(p2.sayHi());
</script>
new 做了三件事:创建空对象 → 把 this 指向它 → 返回这个对象。
(8) Object.keys / values / entries
这三个静态方法分别返回对象的键、值、键值对数组:
| 方法 | 返回 |
|---|---|
Object.keys(obj) |
["name", "age"] |
Object.values(obj) |
["张三", 20] |
Object.entries(obj) |
[["name","张三"], ["age",20]] |
遍历对象时非常好用:Object.keys(obj).forEach(key => ...)。
▶ 示例:创建学生对象并展示信息
HTML
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>对象基础</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.card { border: 2px solid #4a90d9; border-radius: 8px; padding: 16px; max-width: 360px; background: #f0f7ff; }
.card h3 { margin: 0 0 8px; color: #4a90d9; }
.card p { margin: 4px 0; }
</style>
</head>
<body>
<h2>学生信息卡</h2>
<div id="output"></div>
<script>
const student = {
name: "张三",
age: 20,
major: "计算机科学与技术",
gpa: 3.7,
introduce() {
return `我叫${this.name},今年${this.age}岁,专业是${this.major},绩点${this.gpa}。`;
}
};
const output = document.getElementById("output");
output.innerHTML = `
<div class="card">
<h3>${student.name}</h3>
<p>年龄:${student.age}</p>
<p>专业:${student.major}</p>
<p>绩点:${student.gpa}</p>
<p><em>${student.introduce()}</em></p>
</div>
`;
</script>
</body>
</html>
▶ 示例:点语法与方括号访问对比
HTML
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>属性访问方式</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.result { background: #f5f5f5; padding: 12px; border-radius: 6px; margin: 8px 0; }
code { background: #e0e0e0; padding: 2px 6px; border-radius: 3px; }
</style>
</head>
<body>
<h2>属性访问方式对比</h2>
<div id="output"></div>
<script>
const user = {
name: "李华",
age: 28,
"home-city": "北京"
};
const key = "name";
const results = [];
results.push(`user.name → ${user.name}`);
results.push(`user["name"] → ${user["name"]}`);
results.push(`user[key](key="name") → ${user[key]}`);
results.push(`user["home-city"] → ${user["home-city"]}`);
document.getElementById("output").innerHTML = results
.map(r => `<div class="result"><code>${r}</code></div>`)
.join("");
</script>
</body>
</html>
▶ 示例:动态添加、修改、删除属性
HTML
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>操作属性</title>
<style>
body { font-family: sans-serif; padding: 20px; }
table { border-collapse: collapse; margin: 12px 0; }
td, th { border: 1px solid #ccc; padding: 8px 14px; text-align: left; }
th { background: #4a90d9; color: #fff; }
.action { color: #888; font-style: italic; margin: 8px 0; }
</style>
</head>
<body>
<h2>对象属性操作</h2>
<div id="output"></div>
<script>
const product = { name: "笔记本", price: 5999 };
const log = [];
function showState(label) {
log.push({ label, snapshot: JSON.stringify(product) });
}
showState("初始状态");
product.price = 4999;
showState("修改 price 为 4999");
product.brand = "联想";
showState("添加 brand 属性");
delete product.brand;
showState("删除 brand 属性");
const output = document.getElementById("output");
output.innerHTML = "<table><tr><th>操作</th><th>对象状态</th></tr>" +
log.map(r => `<tr><td>${r.label}</td><td>${r.snapshot}</td></tr>`).join("") +
"</table>";
</script>
</body>
</html>
▶ 示例:构造函数与 Object.keys/values/entries
HTML
📖 仅展示
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>构造函数与Object方法</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.section { margin: 16px 0; padding: 12px; background: #f9f9f9; border-radius: 6px; }
.section h3 { margin-top: 0; color: #4a90d9; }
ul { padding-left: 20px; }
li { margin: 4px 0; }
</style>
</head>
<body>
<h2>构造函数 & Object 静态方法</h2>
<div id="output"></div>
<script>
function Phone(brand, model, price) {
this.brand = brand;
this.model = model;
this.price = price;
this.showInfo = function() {
return `${this.brand} ${this.model},售价 ¥${this.price}`;
};
}
const p1 = new Phone("华为", "Mate 60", 5499);
const p2 = new Phone("苹果", "iPhone 15", 5999);
const keys = Object.keys(p1);
const values = Object.values(p1);
const entries = Object.entries(p1);
document.getElementById("output").innerHTML = `
<div class="section">
<h3>构造函数创建的对象</h3>
<p>${p1.showInfo()}</p>
<p>${p2.showInfo()}</p>
</div>
<div class="section">
<h3>Object.keys(p1)</h3>
<ul>${keys.map(k => `<li>${k}</li>`).join("")}</ul>
</div>
<div class="section">
<h3>Object.values(p1)</h3>
<ul>${values.map(v => `<li>${v}</li>`).join("")}</ul>
</div>
<div class="section">
<h3>Object.entries(p1)</h3>
<ul>${entries.map(([k, v]) => `<li><code>${k}</code>: <code>${v}</code></li>`).join("")}</ul>
</div>
`;
</script>
</body>
</html>
❓ 常见问题
Q 用
const 声明的对象还能修改属性吗?A 能。
const 锁的是变量的引用(即让它始终指向同一个对象),而不是对象本身的内容。你可以往里面加属性、改属性、删属性,但不能重新赋值 obj = {}。Q 什么时候用方括号而不是点语法?
A 当属性名包含空格或连字符(如
"home-city"),或者属性名存储在变量中需要动态访问时,必须用方括号。其他情况点语法更简洁,优先使用。Q 构造函数忘记写
new 会怎样?A
this 会指向全局对象(严格模式下是 undefined),导致属性挂错地方甚至报错。这是一个经典坑——后来 ES6 的 class 语法帮你自动处理了这个问题。📖 小节
- 对象用花括号
{}创建,键值对存储数据,点语法和方括号两种方式访问属性 - 方括号适合动态访问和含特殊字符的属性名,点语法更简洁优先使用
- 对象的方法通过
this访问自身属性,注意this指向调用者 - 构造函数用
new批量创建同结构对象,是面向对象编程的基础 Object.keys/values/entries三个静态方法方便遍历对象的键、值、键值对
📝 作业
- 创建一个
book对象,包含title、author、year三个属性和一个getSummary()方法,方法返回"《title》by author, published in year"格式的字符串。 - 写一个构造函数
Car(brand, model, year),用它创建 3 辆车,然后用Object.keys遍历其中一辆车的所有属性名。 - 给上面任意一辆车动态添加一个
drive()方法(返回"品牌型号正在行驶"),然后调用它。体会this在方法中如何指向当前对象。