Search K
Appearance
Appearance
📊 SEO元描述:2024年最新JavaScript对象创建教程,详解字面量创建、构造函数创建、Object.create()方法、工厂函数模式。包含完整代码示例和性能对比,适合前端开发者快速掌握对象创建最佳实践。
核心关键词:JavaScript对象创建2024、对象字面量、构造函数创建对象、Object.create方法、工厂函数模式
长尾关键词:JavaScript怎么创建对象、对象创建方式有哪些、构造函数vs字面量、Object.create用法、JavaScript对象创建最佳实践
通过本节JavaScript对象的创建方式,你将系统性掌握:
对象创建方式是JavaScript面向对象编程的基础。不同的创建方式有不同的性能特征、内存占用、继承关系和使用场景。掌握多种创建方式,能让你在不同场景下选择最合适的解决方案。
💡 核心理解:选择合适的对象创建方式,是写出高质量JavaScript代码的关键
对象字面量是最简单、最直接的对象创建方式,使用花括号{}直接定义对象。
// 🎉 基础字面量创建
const person = {
name: 'Alice',
age: 25,
city: 'New York',
// 方法定义
greet: function() {
return `Hello, I'm ${this.name}`;
},
// ES6简化方法语法
introduce() {
return `I'm ${this.name}, ${this.age} years old, from ${this.city}`;
},
// 计算属性名(ES6)
['full' + 'Name']: 'Alice Johnson'
};
console.log(person.greet()); // "Hello, I'm Alice"
console.log(person.introduce()); // "I'm Alice, 25 years old, from New York"
console.log(person.fullName); // "Alice Johnson"// 🎉 动态创建对象属性
function createUser(name, age, skills) {
const user = {
name: name,
age: age,
createdAt: new Date(),
// 动态添加技能
skills: skills || [],
// 动态方法
addSkill(skill) {
this.skills.push(skill);
},
getProfile() {
return {
name: this.name,
age: this.age,
skillCount: this.skills.length,
memberSince: this.createdAt.getFullYear()
};
}
};
// 根据技能数量动态添加等级
if (user.skills.length > 5) {
user.level = 'Expert';
} else if (user.skills.length > 2) {
user.level = 'Intermediate';
} else {
user.level = 'Beginner';
}
return user;
}
const developer = createUser('Bob', 30, ['JavaScript', 'React', 'Node.js']);
console.log(developer.getProfile());// 🎉 ES6+对象字面量增强功能
const name = 'Charlie';
const age = 28;
const city = 'San Francisco';
const enhancedPerson = {
// 属性简写
name,
age,
city,
// 方法简写
greet() {
return `Hello from ${this.name}`;
},
// 计算属性名
[name.toLowerCase() + 'Info']: 'Personal Information',
// getter和setter
get fullInfo() {
return `${this.name}, ${this.age}, ${this.city}`;
},
set updateAge(newAge) {
if (newAge > 0 && newAge < 150) {
this.age = newAge;
}
},
// 异步方法
async fetchUserData() {
try {
const response = await fetch(`/api/users/${this.name}`);
return await response.json();
} catch (error) {
console.error('Failed to fetch user data:', error);
}
}
};
console.log(enhancedPerson.fullInfo); // "Charlie, 28, San Francisco"
enhancedPerson.updateAge = 29;
console.log(enhancedPerson.age); // 29字面量创建法特点:
构造函数是用于创建特定类型对象的函数,通过new操作符调用。
// 🎉 基础构造函数
function Person(name, age, city) {
// 实例属性
this.name = name;
this.age = age;
this.city = city;
this.createdAt = new Date();
// 实例方法(不推荐,每个实例都会创建新方法)
this.greet = function() {
return `Hello, I'm ${this.name}`;
};
}
// 原型方法(推荐,所有实例共享)
Person.prototype.introduce = function() {
return `I'm ${this.name}, ${this.age} years old, from ${this.city}`;
};
Person.prototype.getAge = function() {
return this.age;
};
Person.prototype.setAge = function(newAge) {
if (newAge > 0 && newAge < 150) {
this.age = newAge;
}
};
// 创建实例
const person1 = new Person('Alice', 25, 'New York');
const person2 = new Person('Bob', 30, 'Los Angeles');
console.log(person1.introduce()); // "I'm Alice, 25 years old, from New York"
console.log(person2.introduce()); // "I'm Bob, 30 years old, from Los Angeles"// 🎉 模拟new操作符的实现
function myNew(constructor, ...args) {
// 1. 创建一个新对象
const obj = {};
// 2. 设置新对象的原型
Object.setPrototypeOf(obj, constructor.prototype);
// 3. 执行构造函数,绑定this
const result = constructor.apply(obj, args);
// 4. 返回对象(如果构造函数返回对象则返回该对象,否则返回新创建的对象)
return result instanceof Object ? result : obj;
}
// 测试自定义new
function Car(brand, model) {
this.brand = brand;
this.model = model;
}
Car.prototype.getInfo = function() {
return `${this.brand} ${this.model}`;
};
const car1 = new Car('Toyota', 'Camry');
const car2 = myNew(Car, 'Honda', 'Civic');
console.log(car1.getInfo()); // "Toyota Camry"
console.log(car2.getInfo()); // "Honda Civic"
console.log(car1 instanceof Car); // true
console.log(car2 instanceof Car); // true// 🎉 高级构造函数模式
function BankAccount(accountNumber, initialBalance = 0) {
// 私有变量(通过闭包实现)
let balance = initialBalance;
let transactions = [];
// 验证账号格式
if (!/^\d{10}$/.test(accountNumber)) {
throw new Error('Invalid account number format');
}
// 公共属性
this.accountNumber = accountNumber;
this.createdAt = new Date();
// 特权方法(可以访问私有变量)
this.deposit = function(amount) {
if (amount > 0) {
balance += amount;
transactions.push({
type: 'deposit',
amount: amount,
timestamp: new Date(),
balance: balance
});
return balance;
}
throw new Error('Deposit amount must be positive');
};
this.withdraw = function(amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
transactions.push({
type: 'withdrawal',
amount: amount,
timestamp: new Date(),
balance: balance
});
return balance;
}
throw new Error('Invalid withdrawal amount');
};
this.getBalance = function() {
return balance;
};
this.getTransactionHistory = function() {
return [...transactions]; // 返回副本,保护原数据
};
}
// 原型方法
BankAccount.prototype.getAccountInfo = function() {
return {
accountNumber: this.accountNumber,
balance: this.getBalance(),
createdAt: this.createdAt
};
};
// 使用示例
const account = new BankAccount('1234567890', 1000);
account.deposit(500);
account.withdraw(200);
console.log(account.getBalance()); // 1300
console.log(account.getTransactionHistory());构造函数创建法特点:
**Object.create()**方法创建一个新对象,使用现有对象作为新对象的原型。
// 🎉 基础Object.create()用法
const personPrototype = {
greet: function() {
return `Hello, I'm ${this.name}`;
},
introduce: function() {
return `I'm ${this.name}, ${this.age} years old`;
},
setAge: function(age) {
if (age > 0 && age < 150) {
this.age = age;
}
}
};
// 创建以personPrototype为原型的对象
const person1 = Object.create(personPrototype);
person1.name = 'Alice';
person1.age = 25;
const person2 = Object.create(personPrototype);
person2.name = 'Bob';
person2.age = 30;
console.log(person1.greet()); // "Hello, I'm Alice"
console.log(person2.introduce()); // "I'm Bob, 30 years old"
// 检查原型关系
console.log(Object.getPrototypeOf(person1) === personPrototype); // true// 🎉 使用属性描述符创建对象
const userPrototype = {
login: function() {
console.log(`${this.username} logged in`);
},
logout: function() {
console.log(`${this.username} logged out`);
}
};
const user = Object.create(userPrototype, {
username: {
value: 'john_doe',
writable: true,
enumerable: true,
configurable: true
},
email: {
value: 'john@example.com',
writable: true,
enumerable: true,
configurable: false
},
id: {
value: Math.random().toString(36).substr(2, 9),
writable: false,
enumerable: true,
configurable: false
},
// 访问器属性
fullProfile: {
get: function() {
return `${this.username} (${this.email})`;
},
enumerable: true,
configurable: true
}
});
console.log(user.fullProfile); // "john_doe (john@example.com)"
user.login(); // "john_doe logged in"
// 尝试修改只读属性
user.id = 'new_id'; // 静默失败(严格模式下会报错)
console.log(user.id); // 原值不变// 🎉 使用Object.create()实现继承
const Animal = {
init: function(name, species) {
this.name = name;
this.species = species;
return this;
},
makeSound: function() {
return `${this.name} makes a sound`;
},
getInfo: function() {
return `${this.name} is a ${this.species}`;
}
};
const Dog = Object.create(Animal);
Dog.init = function(name, breed) {
Animal.init.call(this, name, 'Dog');
this.breed = breed;
return this;
};
Dog.makeSound = function() {
return `${this.name} barks`;
};
Dog.fetch = function() {
return `${this.name} fetches the ball`;
};
// 创建实例
const myDog = Object.create(Dog).init('Buddy', 'Golden Retriever');
console.log(myDog.makeSound()); // "Buddy barks"
console.log(myDog.getInfo()); // "Buddy is a Dog"
console.log(myDog.fetch()); // "Buddy fetches the ball"
// 检查原型链
console.log(Object.getPrototypeOf(myDog) === Dog); // true
console.log(Object.getPrototypeOf(Dog) === Animal); // trueObject.create()特点:
工厂函数是返回对象的普通函数,提供了一种函数式的对象创建方式。
// 🎉 基础工厂函数
function createPerson(name, age, city) {
return {
name: name,
age: age,
city: city,
greet() {
return `Hello, I'm ${this.name}`;
},
introduce() {
return `I'm ${this.name}, ${this.age} years old, from ${this.city}`;
},
moveTo(newCity) {
this.city = newCity;
return `${this.name} moved to ${newCity}`;
}
};
}
// 创建对象
const person1 = createPerson('Alice', 25, 'New York');
const person2 = createPerson('Bob', 30, 'Los Angeles');
console.log(person1.greet()); // "Hello, I'm Alice"
console.log(person2.moveTo('Chicago')); // "Bob moved to Chicago"// 🎉 工厂函数实现私有变量
function createCounter(initialValue = 0) {
// 私有变量
let count = initialValue;
let history = [];
return {
// 公共方法
increment() {
count++;
history.push({ action: 'increment', value: count, timestamp: Date.now() });
return count;
},
decrement() {
count--;
history.push({ action: 'decrement', value: count, timestamp: Date.now() });
return count;
},
getValue() {
return count;
},
reset() {
count = initialValue;
history.push({ action: 'reset', value: count, timestamp: Date.now() });
return count;
},
getHistory() {
return [...history]; // 返回副本
},
// 链式调用支持
add(value) {
count += value;
history.push({ action: 'add', value: count, timestamp: Date.now() });
return this; // 返回自身支持链式调用
}
};
}
const counter = createCounter(10);
console.log(counter.increment()); // 11
console.log(counter.add(5).add(3).getValue()); // 19
console.log(counter.getHistory());// 🎉 可配置的工厂函数
function createApiClient(baseUrl, options = {}) {
const config = {
timeout: 5000,
retries: 3,
headers: {
'Content-Type': 'application/json'
},
...options
};
// 私有方法
function makeRequest(method, endpoint, data = null) {
const url = `${baseUrl}${endpoint}`;
const requestOptions = {
method,
headers: config.headers,
timeout: config.timeout
};
if (data) {
requestOptions.body = JSON.stringify(data);
}
return fetch(url, requestOptions);
}
function retry(fn, retries = config.retries) {
return fn().catch(error => {
if (retries > 0) {
console.log(`Retrying... ${retries} attempts left`);
return retry(fn, retries - 1);
}
throw error;
});
}
// 返回公共接口
return {
get(endpoint) {
return retry(() => makeRequest('GET', endpoint));
},
post(endpoint, data) {
return retry(() => makeRequest('POST', endpoint, data));
},
put(endpoint, data) {
return retry(() => makeRequest('PUT', endpoint, data));
},
delete(endpoint) {
return retry(() => makeRequest('DELETE', endpoint));
},
setHeader(key, value) {
config.headers[key] = value;
return this;
},
setTimeout(timeout) {
config.timeout = timeout;
return this;
},
getConfig() {
return { ...config };
}
};
}
// 使用示例
const apiClient = createApiClient('https://api.example.com')
.setHeader('Authorization', 'Bearer token123')
.setTimeout(10000);
// apiClient.get('/users').then(response => response.json());工厂函数模式特点:
// 🎉 性能测试示例
console.time('字面量创建');
for (let i = 0; i < 100000; i++) {
const obj = {
name: 'test',
value: i,
method() { return this.value; }
};
}
console.timeEnd('字面量创建');
console.time('构造函数创建');
function TestConstructor(name, value) {
this.name = name;
this.value = value;
}
TestConstructor.prototype.method = function() { return this.value; };
for (let i = 0; i < 100000; i++) {
const obj = new TestConstructor('test', i);
}
console.timeEnd('构造函数创建');
console.time('Object.create创建');
const prototype = {
method() { return this.value; }
};
for (let i = 0; i < 100000; i++) {
const obj = Object.create(prototype);
obj.name = 'test';
obj.value = i;
}
console.timeEnd('Object.create创建');
console.time('工厂函数创建');
function createTest(name, value) {
return {
name,
value,
method() { return this.value; }
};
}
for (let i = 0; i < 100000; i++) {
const obj = createTest('test', i);
}
console.timeEnd('工厂函数创建');| 创建方式 | 适用场景 | 优点 | 缺点 | 性能 |
|---|---|---|---|---|
| 字面量 | 单个对象、配置对象 | 简洁直观 | 不适合批量创建 | 最快 |
| 构造函数 | 批量创建、需要继承 | 支持instanceof、原型共享 | 语法复杂 | 快 |
| Object.create | 精确控制原型链 | 灵活的原型控制 | 语法相对复杂 | 中等 |
| 工厂函数 | 需要私有变量、函数式风格 | 真正私有性、灵活 | 内存占用较大 | 较慢 |
通过本节JavaScript对象的创建方式的学习,你已经掌握:
A: 创建单个、独特的对象时使用字面量;需要创建多个相似对象或建立继承关系时使用构造函数。字面量适合配置对象,构造函数适合实体对象。
A: Object.create(null)创建一个没有原型的纯净对象,常用作字典或映射,避免继承Object.prototype的方法,防止属性名冲突。
A: 工厂函数是普通函数返回对象,构造函数需要new调用。工厂函数可以实现真正的私有变量,构造函数支持instanceof检测和原型继承。
A: 考虑因素:1)是否需要批量创建 2)是否需要继承 3)是否需要私有变量 4)性能要求 5)团队编码风格。一般情况下,简单对象用字面量,复杂对象用构造函数或类。
A: class是构造函数的语法糖,提供更清晰的语法。class必须用new调用,有更严格的语法检查,支持extends继承,但本质上仍是基于原型的继承。
"掌握多种对象创建方式,就像掌握了不同的工具。选择合适的工具解决合适的问题,是优秀开发者的标志!"