JavaScript 自定义对象详解
自定义对象是 JavaScript 的核心编程范式,通过组合属性+方法创建特定数据结构。以下是 5 种创建方式及深度应用:
一、对象创建的 5 种方式
1. 对象字面量(最常用)
const user = {
// 属性
name: "Alice",
age: 28,
// 方法
greet() {
return `Hello, I'm ${this.name}`;
},
// 计算属性名
["id_" + Date.now()]: "123X"
};
console.log(user.greet()); // "Hello, I'm Alice"
2. 构造函数(创建相似对象)
function Person(name, age) {
// 实例属性
this.name = name;
this.age = age;
// 实例方法
this.sayAge = function() {
console.log(`I'm ${this.age} years old`);
};
}
// 原型方法(共享内存)
Person.prototype.intro = function() {
return `Name: ${this.name}, Age: ${this.age}`;
};
const bob = new Person("Bob", 30);
bob.sayAge(); // "I'm 30 years old"
3. Object.create()
(基于原型创建)
const animal = {
type: "Unknown",
describe() {
return `This is a ${this.type}`;
}
};
const dog = Object.create(animal);
dog.type = "Dog"; // 覆盖原型属性
console.log(dog.describe()); // "This is a Dog"
4. class
语法(ES6 面向对象)
class Product {
// 构造函数
constructor(name, price) {
this.name = name;
this.price = price;
}
// 实例方法
formatPrice() {
return `$${this.price.toFixed(2)}`;
}
// Getter
get discountPrice() {
return this.price * 0.9;
}
// 静态方法
static compare(a, b) {
return a.price - b.price;
}
}
const book = new Product("JS Guide", 29.99);
console.log(book.discountPrice); // 26.991
5. 工厂函数(无 new
创建)
function createUser(name) {
let loginCount = 0; // 私有变量
return {
login() {
loginCount++;
return `${name} logged in ${loginCount} times`;
}
};
}
const user = createUser("Chris");
console.log(user.login()); // "Chris logged in 1 times"
二、对象操作进阶技巧
1. 属性描述符控制
const obj = {};
Object.defineProperty(obj, "secret", {
value: "confidential",
writable: false, // 不可修改
enumerable: false, // 不可枚举
configurable: false // 不可删除
});
obj.secret = "new"; // 静默失败(严格模式报错)
console.log(obj.secret); // "confidential"
2. 动态属性名
const dynamicKey = "status";
const order = {
id: 1001,
[dynamicKey + "_code"]: "PAID" // 计算属性名
};
console.log(order.status_code); // "PAID"
3. 对象合并与克隆
const defaults = { theme: "light", fontSize: 16 };
const userSettings = { fontSize: 18 };
// 浅合并
const settings = Object.assign({}, defaults, userSettings);
// 深克隆(简单对象)
const deepClone = JSON.parse(JSON.stringify(defaults));
三、对象设计模式
1. 模块模式(封装私有状态)
const Counter = (function() {
let count = 0; // 私有变量
return {
increment() {
count++;
return count;
},
reset() {
count = 0;
}
};
})();
Counter.increment(); // 1
Counter.count; // undefined(无法访问)
2. 组合模式(混合功能)
const canEat = {
eat() { console.log("Eating...") }
};
const canWalk = {
walk() { console.log("Walking...") }
};
class Human {}
Object.assign(Human.prototype, canEat, canWalk);
const person = new Human();
person.eat(); // "Eating..."
3. 观察者模式(事件驱动)
class EventEmitter {
constructor() {
this.events = {};
}
on(event, listener) {
(this.events[event] || (this.events[event] = [])).push(listener);
}
emit(event, ...args) {
this.events[event]?.forEach(fn => fn(...args));
}
}
// 使用
const emitter = new EventEmitter();
emitter.on("login", user => console.log(`${user} logged in`));
emitter.emit("login", "Alice"); // "Alice logged in"
四、最佳实践与陷阱
✅ 推荐做法
- 优先
class
语法:结构清晰,易维护 - 封装私有字段:使用
#
前缀(ES2022)class Wallet { #balance = 0; // 私有字段 deposit(amount) { this.#balance += amount } }
- 对象冻结:防止意外修改
const config = Object.freeze({ API_KEY: "XYZ" }); config.API_KEY = "ABC"; // 静默失败(严格模式报错)
⚠️ 常见陷阱
this
丢失问题const timer = { delay: 1000, start() { setTimeout(function() { console.log(this.delay); // undefined(this指向window) }, 100); } }; // 修复:使用箭头函数或 .bind(this)
- 原型污染
// 禁止修改内置原型 Array.prototype.sum = function() { /*...*/ } // 危险!
五、自定义对象 vs 内置对象
特性 | 自定义对象 | 内置对象 |
---|---|---|
创建方式 | 手动定义 | 语言自带 |
扩展性 | 完全可控 | 部分受限 |
内存占用 | 按需设计 | 固定开销 |
适用场景 | 业务模型 | 通用功能 |
💡 核心价值:自定义对象将数据+行为封装为独立单元,实现高内聚低耦合,是构建复杂应用的基础。例如 Vue/React 组件本质是自定义对象的扩展。