一、Object 基本概念
JavaScript 中的对象是无序的键值对(key-value pairs)集合,其中:
-
键(key):也称为属性名,必须是字符串或 Symbol 类型(非字符串会自动转换为字符串)。
-
值(value):可以是任意数据类型(原始值、对象、函数等),当值为函数时,该属性称为 "方法"。
简单示例:
const person = {
name: "Alice", // 字符串属性
age: 25, // 数字属性
isStudent: true, // 布尔属性
hobbies: ["读书", "编程"], // 数组属性
greet: function() { // 方法
console.log(`你好,我是${this.name}`);
}
};
二、创建对象的 5 种方式
JavaScript 提供了多种创建对象的方式,不同场景适用不同方法:
1. 对象字面量(最常用)
直接通过{}定义,简洁直观,适合创建单个对象。
const obj = { key: "value" };
2. new Object() 构造函数
通过内置的Object构造函数创建,效果与字面量类似,但更繁琐。
const obj = new Object();
obj.key = "value";
3. 自定义构造函数
通过function定义构造函数,结合new关键字批量创建相似对象(ES6 之前的面向对象实现方式)。
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log(`我是${this.name}`);
};
}
const alice = new Person("Alice", 25);
4. Object.create()
基于现有对象作为原型创建新对象,可灵活控制原型链。
const parent = {
greet: function() {
console.log("Hello");
}
};
const child = Object.create(parent); // child的原型是parent
5. ES6 class 语法糖
ES6 引入的class关键字,本质是构造函数的语法糖,更符合传统面向对象编程的写法。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`我是${this.name}`);
}
}
const bob = new Person("Bob", 30);
三、对象属性的核心操作
掌握属性的访问、添加、删除和检查是使用对象的基础。
1. 访问属性
-
点语法:适用于属性名是合法标识符(无空格、特殊字符,不以数字开头)的情况。
console.log(person.name); // "Alice" -
中括号语法:适用于属性名包含特殊字符、空格,或需要动态计算属性名的情况。
console.log(person["age"]); // 25 const key = "hobbies"; console.log(person[key]); // ["读书", "编程"]
2. 添加 / 修改属性
直接通过赋值即可添加新属性或修改已有属性。
person.gender = "女"; // 添加新属性
person.age = 26; // 修改已有属性
3. 删除属性
使用delete关键字删除对象的属性(注意:只能删除对象自身的属性,无法删除原型上的属性)。
delete person.isStudent;
4. 检查属性是否存在
-
in运算符:检查对象自身或原型链上是否存在该属性。console.log("name" in person); // true console.log("toString" in person); // true(toString是原型上的方法) -
hasOwnProperty()方法:仅检查对象自身是否存在该属性(推荐用于避免原型链干扰)。console.log(person.hasOwnProperty("name")); // true console.log(person.hasOwnProperty("toString")); // false
四、属性的特性:数据属性与访问器属性
JavaScript 的对象属性不仅是简单的键值对,还包含 4 个内部特性(通过Object.defineProperty()定义)。
1. 数据属性
用于存储数据值,包含 4 个特性:
|--------------------|--------------------------------------------------|-------------|
| 特性 | 说明 | 默认值(字面量创建) |
| value | 属性的值 | undefined |
| writable | 属性值是否可修改(true= 可修改,false= 只读) | true |
| enumerable | 属性是否可枚举(true= 可通过for...in或Object.keys()遍历) | true |
| configurable | 属性是否可删除或修改特性(true= 可删除 / 修改,false= 不可操作) | true |
示例:定义一个只读且不可枚举的属性
const obj = {};
Object.defineProperty(obj, "id", {
value: 1001,
writable: false, // 只读
enumerable: false, // 不可枚举
configurable: false // 不可删除/修改特性
});
2. 访问器属性
不直接存储数据值,而是通过getter和setter函数控制属性的访问与赋值,包含 4 个特性:
|--------------------|----------------------------|-------------|
| 特性 | 说明 | 默认值 |
| get | 读取属性时调用的函数(无参数,返回值作为属性值) | undefined |
| set | 写入属性时调用的函数(接收一个参数,用于设置属性值) | undefined |
| enumerable | 同数据属性 | true |
| configurable | 同数据属性 | true |
示例:通过访问器属性实现 "年龄必须为正整数" 的校验
const person = {
_age: 0 // 下划线表示私有属性(约定俗成,非真正私有)
};
Object.defineProperty(person, "age", {
get: function() { return this._age; },
set: function(value) {
if (typeof value === "number" && value > 0 && Number.isInteger(value)) {
this._age = value;
} else {
console.log("年龄必须是正整数!");
}
}, enumerable: true, configurable: true });
person.age = 25; // 正常赋值
person.age = -5; // 输出"年龄必须是正整数!"
五、Object 常用静态方法
JavaScript 提供了多个内置的静态方法(直接通过Object.xxx()调用),用于操作对象。
|-----------------------------------------|---------------------------------------------|--------------------------------------------------------------------|
| 方法 | 作用 | 示例 |
| Object.keys(obj) | 返回对象自身可枚举属性的键组成的数组 | Object.keys(person) → ["name", "age", "hobbies", "greet"] |
| Object.values(obj) | 返回对象自身可枚举属性的值组成的数组 | Object.values(person) → ["Alice", 25, ["读书", "编程"], function] |
| Object.entries(obj) | 返回对象自身可枚举属性 的键值对数组(每个元素是[key, value]) | Object.entries(person) → [["name", "Alice"], ["age", 25], ...] |
| Object.assign(target, ...sources) | 将多个源对象的自身可枚举属性复制到目标对象(浅拷贝) | const newObj = Object.assign({}, person, { gender: "女" }) |
| Object.freeze(obj) | 冻结对象:禁止添加 / 删除 / 修改属性,且属性特性不可修改(彻底只读) | Object.freeze(person); person.age = 26; // 无效 |
| Object.seal(obj) | 密封对象:禁止添加 / 删除属性,但可修改已有属性的值 | Object.seal(person); delete person.name; // 无效 |
| Object.getPrototypeOf(obj) | 获取对象的原型(即__proto__) | Object.getPrototypeOf(child) === parent → true |
| Object.setPrototypeOf(obj, proto) | 设置对象的原型(性能较差,推荐用Object.create()) | Object.setPrototypeOf(child, newParent) |
六、原型与原型链:Object 的核心机制
JavaScript 的面向对象编程基于原型链实现,理解原型是掌握 Object 的关键。
1. 三个核心概念
-
__proto__:每个对象(除了null)都有一个隐式原型属性__proto__,指向它的原型对象。 -
prototype:每个函数(除了箭头函数)都有一个显式原型属性prototype,指向一个对象(该对象包含通过该构造函数创建的实例共享的属性和方法)。 -
constructor:原型对象上有一个constructor属性,指向对应的构造函数。
简单关系示例:
function Person() {} const alice = new Person();
// 实例的__proto__指向构造函数的
prototype console.log(alice.__proto__ === Person.prototype); // true
// 原型的constructor指向构造函数
console.log(Person.prototype.constructor === Person); // true
2. 原型链的工作原理
当访问对象的某个属性时,JavaScript 会先在对象自身查找:
-
若找到,直接返回;
-
若没找到,继续通过
__proto__到原型对象上查找; -
若原型对象上也没找到,继续到原型的原型上查找,直到
null(原型链的顶端); -
若全程未找到,返回
undefined。
示例:
// 所有对象的原型链最终指向
Object.prototype console.log(alice.toString());
// 调用的是
Object.prototype.toString()
七、Object 核心知识汇总表
为了方便快速查阅,将 Object 的核心知识点整理如下:
|----------|------------------------------------------------------------------------------------------------------|
| 分类 | 核心内容 |
| 创建方式 | 对象字面量、new Object()、自定义构造函数、Object.create()、ES6 class |
| 属性操作 | 访问(点 / 中括号)、添加 / 修改、删除(delete)、检查(in/hasOwnProperty()) |
| 属性特性 | 数据属性(value/writable/enumerable/configurable)、访问器属性(get/set) |
| 常用方法 | Object.keys()/values()/entries()、Object.assign()、Object.freeze()、Object.getPrototypeOf() |
| 原型机制 | __proto__、prototype、constructor、原型链查找规则 |
总结
Object 是 JavaScript 中最基础且最重要的数据结构,从简单的键值对存储到复杂的面向对象编程,都离不开 Object 的支持。通过本文的学习,你应该掌握了对象的创建、属性操作、特性定义、常用方法以及原型链的核心机制。结合汇总表格,你可以快速回顾和巩固这些知识点,为后续的 JavaScript 学习打下坚实基础。