创建对象的方法有哪些?从基础到进阶的完整指南
一、开篇:对象 ------JavaScript 世界的核心基石
在 JavaScript 中,对象是一种复合数据类型,也是构建整个 JS 生态的核心:无论是 DOM 操作、数据管理,还是面向对象编程(OOP),都离不开对象的创建与使用。
JavaScript 提供了多种创建对象的方法,从最基础的 "字面量" 到进阶的 "构造函数""类",再到灵活的 "原型继承""工厂模式",不同方法适用于不同的开发场景。很多初学者容易混淆各类方法的适用场景,甚至写出冗余、难以维护的代码。本文将从基础到进阶,系统梳理 JavaScript 中 8 种创建对象的方法,结合实战示例、优缺点和适用场景,帮你彻底掌握对象创建的精髓。
二、第一类:基础创建方法(入门级)
这类方法简单直观,适合创建单个、简单的对象,是初学者最先接触的对象创建方式。
1. 对象字面量(Object Literal):最简洁的创建方式
核心语法 :通过{}直接定义对象的属性和方法,是 JavaScript 中最常用、最简洁的对象创建方式。语法格式:
javascript
运行
const obj = {
// 数据属性
key1: value1,
key2: value2,
// 方法属性
method1: function() {
// 方法逻辑
},
// ES6简写方法
method2() {
// 方法逻辑
}
};
实战示例:
javascript
运行
// 创建用户对象
const user = {
name: "张三",
age: 25,
gender: "男",
// 普通方法
sayHello: function() {
console.log(`你好,我是${this.name}`);
},
// ES6简写方法(推荐)
getAge() {
return this.age;
}
};
// 使用对象
console.log(user.name); // 输出:张三
user.sayHello(); // 输出:你好,我是张三
console.log(user.getAge()); // 输出:25
核心特点:
- ✅ 优点:语法简洁、直观,无需额外关键字,性能最优(直接创建对象,无额外函数调用);
- ❌ 缺点:无法复用,创建多个相似对象时会产生大量重复代码;
- 🎯 适用场景:创建单个、简单的对象(如配置对象、临时数据对象)。
2. new Object ():构造函数创建(字面量的 "完整版")
核心语法 :通过new Object()调用 Object 构造函数创建对象,再动态添加属性和方法,本质是对象字面量的 "底层实现"。语法格式:
javascript
运行
const obj = new Object();
// 动态添加属性
obj.key1 = value1;
obj.key2 = value2;
// 动态添加方法
obj.method = function() {};
实战示例:
javascript
运行
// 创建商品对象
const product = new Object();
product.id = 1001;
product.name = "JavaScript进阶指南";
product.price = 89.9;
product.getPrice = function() {
return `¥${this.price}`;
};
console.log(product.name); // 输出:JavaScript进阶指南
console.log(product.getPrice()); // 输出:¥89.9
核心特点:
- ✅ 优点:支持动态添加属性 / 方法,适合属性不确定的场景;
- ❌ 缺点:代码冗余(相比字面量),创建多个相似对象时重复代码更多;
- 🎯 适用场景:极少使用(仅兼容旧代码或动态添加属性的特殊场景),推荐优先使用对象字面量。
对象字面量 vs new Object ():
- 二者本质等价(
{}是new Object()的语法糖); - 字面量更简洁,是行业通用的最佳实践;
new Object()可传入参数(如new Object(123)创建 Number 对象),但无实际开发价值。
三、第二类:可复用创建方法(进阶级)
这类方法解决了 "重复创建相似对象" 的问题,支持代码复用,是面向对象编程的基础。
3. 工厂函数(Factory Function):批量创建相似对象
核心思想 :封装一个函数,函数内部通过字面量创建对象,动态添加属性 / 方法后返回该对象,调用函数即可批量创建相似对象。语法格式:
javascript
运行
function createObject(param1, param2) {
// 创建空对象
const obj = {};
// 动态添加属性(基于参数)
obj.prop1 = param1;
obj.prop2 = param2;
// 添加方法
obj.method = function() {};
// 返回对象
return obj;
}
实战示例(创建用户对象工厂):
javascript
运行
// 定义用户工厂函数
function createUser(name, age, gender) {
const user = {};
// 公共属性(基于参数)
user.name = name;
user.age = age;
user.gender = gender;
// 公共方法
user.sayHello = function() {
console.log(`你好,我是${this.name},今年${this.age}岁`);
};
return user;
}
// 批量创建用户对象
const user1 = createUser("张三", 25, "男");
const user2 = createUser("李四", 28, "女");
user1.sayHello(); // 输出:你好,我是张三,今年25岁
user2.sayHello(); // 输出:你好,我是李四,今年28岁
核心特点:
- ✅ 优点:支持批量创建相似对象,减少重复代码,代码结构清晰;
- ❌ 缺点:每个对象的方法都是独立的函数实例(内存占用高),无法区分对象类型(所有对象都是 Object 类型);
- 🎯 适用场景:批量创建简单的相似对象(无复杂继承、类型区分需求)。
4. 构造函数(Constructor Function):面向对象的基础
核心思想 :通过new关键字调用自定义函数,函数内部通过this绑定属性 / 方法,自动创建并返回对象,是 JS 实现 "类" 的基础。语法规则:
- 构造函数名首字母大写(约定俗成,区分普通函数);
- 函数内部通过
this定义属性 / 方法; - 无需手动创建对象和返回对象(
new关键字自动完成); - 调用时必须加
new(否则this指向全局对象,导致全局变量污染)。
语法格式:
javascript
运行
function ConstructorName(param1, param2) {
// 实例属性
this.prop1 = param1;
this.prop2 = param2;
// 实例方法
this.method = function() {};
}
// 创建对象
const obj = new ConstructorName(value1, value2);
实战示例(用户构造函数):
javascript
运行
// 定义用户构造函数
function User(name, age, gender) {
// 实例属性
this.name = name;
this.age = age;
this.gender = gender;
// 实例方法
this.sayHello = function() {
console.log(`你好,我是${this.name},今年${this.age}岁`);
};
}
// 创建用户实例
const user1 = new User("张三", 25, "男");
const user2 = new User("李四", 28, "女");
user1.sayHello(); // 输出:你好,我是张三,今年25岁
// 区分对象类型(构造函数的核心优势)
console.log(user1 instanceof User); // true
console.log(user2 instanceof User); // true
核心优化:原型方法(解决方法重复创建问题) 构造函数内部定义的方法,每个实例都会创建一个新的函数副本(内存浪费),通过原型(prototype)定义方法,所有实例共享同一个方法:
javascript
运行
// 构造函数(仅定义属性)
function User(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
// 原型方法(所有实例共享)
User.prototype.sayHello = function() {
console.log(`你好,我是${this.name},今年${this.age}岁`);
};
// 所有实例共享同一个sayHello方法
const user1 = new User("张三", 25, "男");
const user2 = new User("李四", 28, "女");
console.log(user1.sayHello === user2.sayHello); // true(内存复用)
核心特点:
- ✅ 优点:支持批量创建相似对象,可通过
instanceof区分对象类型,原型方法实现内存复用; - ❌ 缺点:语法相对复杂,原型链理解成本高,继承实现繁琐;
- 🎯 适用场景:需要区分对象类型、批量创建复杂对象(如组件、模块实例)。
5. ES6 Class:构造函数的语法糖
核心思想 :ES6 引入class关键字,是构造函数 + 原型的 "语法糖",提供更接近传统面向对象语言的类定义方式,本质仍基于原型链。核心语法:
class定义类名(首字母大写);constructor方法:类的构造函数(初始化属性);- 类内部直接定义方法(自动挂载到原型上);
- 通过
new创建实例。
语法格式:
javascript
运行
class ClassName {
// 构造函数(初始化属性)
constructor(param1, param2) {
this.prop1 = param1;
this.prop2 = param2;
}
// 原型方法(所有实例共享)
method1() {}
// 静态方法(类本身的方法,非实例方法)
static method2() {}
}
// 创建实例
const obj = new ClassName(value1, value2);
实战示例(用户类):
javascript
运行
// 定义用户类
class User {
// 构造函数
constructor(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
// 原型方法
sayHello() {
console.log(`你好,我是${this.name},今年${this.age}岁`);
}
// 静态方法(通过类调用,而非实例)
static createAdmin() {
return new User("管理员", 0, "未知");
}
}
// 创建普通实例
const user1 = new User("张三", 25, "男");
user1.sayHello(); // 输出:你好,我是张三,今年25岁
// 调用静态方法创建实例
const admin = User.createAdmin();
admin.sayHello(); // 输出:你好,我是管理员,今年0岁
// 类型判断
console.log(user1 instanceof User); // true
核心特点:
- ✅ 优点:语法清晰、符合传统 OOP 习惯,支持继承(
extends)、静态方法、私有属性(ES2022+); - ❌ 缺点:本质是原型链的语法糖,底层逻辑仍需理解原型;
- 🎯 适用场景:现代 JS 开发(React/Vue 组件、Node.js 模块),需要清晰的类结构、继承关系。
四、第三类:灵活创建方法(高级级)
这类方法适用于特殊场景(如继承、克隆、动态属性),是前端进阶开发的必备技能。
6. Object.create ():基于原型创建对象
核心思想 :通过Object.create(prototype, properties)创建新对象,新对象的原型直接指向指定的原型对象,支持自定义属性描述符。语法格式:
javascript
运行
// 基于原型对象创建新对象
const obj = Object.create(prototypeObj, {
// 自定义属性(可选)
prop1: {
value: "xxx", // 属性值
writable: true, // 是否可修改
enumerable: true, // 是否可枚举(for...in遍历)
configurable: true // 是否可删除/修改属性描述符
}
});
实战示例 1:基于原型创建对象
javascript
运行
// 定义原型对象
const userPrototype = {
sayHello: function() {
console.log(`你好,我是${this.name}`);
}
};
// 基于原型创建用户对象
const user1 = Object.create(userPrototype, {
name: { value: "张三", writable: true, enumerable: true },
age: { value: 25, writable: true, enumerable: true }
});
user1.sayHello(); // 输出:你好,我是张三
console.log(user1.__proto__ === userPrototype); // true(原型指向明确)
实战示例 2:实现简单继承
javascript
运行
// 父类原型
const parent = {
getName() {
return this.name;
}
};
// 子类对象(继承父类原型)
const child = Object.create(parent);
child.name = "李四";
console.log(child.getName()); // 输出:李四(继承父类方法)
核心特点:
- ✅ 优点:原型指向明确,支持精细的属性配置,简化继承实现;
- ❌ 缺点:语法相对复杂,属性描述符配置繁琐;
- 🎯 适用场景:自定义原型链、实现继承、精细控制对象属性(如不可修改、不可枚举)。
7. Object.assign ():合并创建对象
核心思想 :将一个或多个源对象的属性复制到目标对象,返回合并后的目标对象,常用于 "基于已有对象创建新对象"。语法格式:
javascript
运行
// 合并源对象到目标对象(目标对象为空对象时,即创建新对象)
const newObj = Object.assign({}, sourceObj1, sourceObj2);
实战示例(创建合并对象):
javascript
运行
// 基础配置对象
const baseConfig = {
theme: "light",
size: "medium"
};
// 自定义配置对象
const customConfig = {
theme: "dark",
fontSize: 16
};
// 合并创建新配置对象(baseConfig不变,customConfig覆盖同名属性)
const finalConfig = Object.assign({}, baseConfig, customConfig);
console.log(finalConfig);
// 输出:{ theme: 'dark', size: 'medium', fontSize: 16 }
console.log(baseConfig); // 输出:{ theme: 'light', size: 'medium' }(原对象不变)
核心特点:
- ✅ 优点:快速合并多个对象,创建新对象(不修改原对象),语法简洁;
- ❌ 缺点:仅支持浅拷贝(深层嵌套对象仍为引用),无法合并不可枚举属性;
- 🎯 适用场景:合并配置对象、基于已有对象扩展属性(如组件 props、请求参数)。
8. 解构赋值 + 展开运算符:灵活创建新对象
核心思想 :ES6 的展开运算符(...)和解构赋值,支持 "基于已有对象创建新对象",可灵活筛选、扩展属性。语法格式:
javascript
运行
// 展开运算符创建新对象
const newObj = { ...sourceObj, newProp: value };
// 解构赋值提取属性+创建新对象
const { prop1, ...rest } = sourceObj;
const newObj2 = { ...rest, newProp: value };
实战示例:
javascript
运行
// 原始对象
const user = {
name: "张三",
age: 25,
gender: "男",
address: "北京"
};
// 1. 扩展属性创建新对象
const userWithId = { ...user, id: 1001 };
console.log(userWithId);
// 输出:{ name: '张三', age: 25, gender: '男', address: '北京', id: 1001 }
// 2. 筛选属性创建新对象(排除address)
const { address, ...userWithoutAddress } = user;
console.log(userWithoutAddress);
// 输出:{ name: '张三', age: 25, gender: '男' }
// 3. 覆盖属性创建新对象
const userWithNewAge = { ...user, age: 26 };
console.log(userWithNewAge.age); // 输出:26(原对象age不变)
核心特点:
- ✅ 优点:语法简洁、灵活,支持属性筛选、扩展、覆盖,符合现代 JS 开发习惯;
- ❌ 缺点:仅支持浅拷贝,低版本浏览器需转译;
- 🎯 适用场景:React/Vue 等框架中状态管理(如修改 state 不影响原状态)、对象属性灵活重组。
五、各类创建方法对比与选型指南
| 方法类型 | 核心语法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 对象字面量 | {} |
简洁、高效、直观 | 无法复用,重复代码多 | 单个、简单对象(配置、临时数据) |
| new Object() | new Object() |
动态添加属性 | 冗余、性能差 | 兼容旧代码、动态属性场景(极少使用) |
| 工厂函数 | 自定义函数 + return | 批量创建、结构清晰 | 方法重复创建、无类型区分 | 简单批量创建相似对象 |
| 构造函数 | new 构造函数() |
类型区分、原型复用 | 语法复杂、继承繁琐 | 复杂对象、需要类型区分 |
| ES6 Class | class + new |
语法清晰、支持继承 / 静态方法 | 原型链底层仍需理解 | 现代开发、类结构、继承关系 |
| Object.create() | Object.create() |
原型指向明确、精细属性配置 | 语法复杂、配置繁琐 | 自定义原型链、继承、属性精细控制 |
| Object.assign() | Object.assign() |
快速合并对象、不修改原对象 | 浅拷贝、不支持不可枚举属性 | 合并配置、扩展已有对象 |
| 展开运算符 | { ...obj } |
灵活筛选 / 扩展属性、符合现代习惯 | 浅拷贝、低版本需转译 | 框架状态管理、对象属性重组 |
六、注意事项:避免对象创建的常见坑
-
浅拷贝 vs 深拷贝:
- 字面量、
Object.assign()、展开运算符、Object.create()均为浅拷贝(深层嵌套对象为引用); - 如需深拷贝,可使用
JSON.parse(JSON.stringify())(不支持函数 / RegExp)或lodash.cloneDeep()。
- 字面量、
-
构造函数调用时遗漏 new:
-
构造函数 / 类调用时必须加
new,否则this指向全局对象(浏览器为window),导致全局变量污染:javascript
运行
function User(name) { this.name = name; } const user = User("张三"); // 无new,this指向window console.log(window.name); // 输出:张三(全局污染)
-
-
Class 的 constructor 遗漏 this:
-
Class 的
constructor中必须通过this绑定属性,否则属性不会挂载到实例上:javascript
运行
class User { constructor(name) { name = name; // 错误:未绑定到this // 正确:this.name = name; } } const user = new User("张三"); console.log(user.name); // undefined
-
-
原型方法的 this 指向:
-
原型方法中的
this指向调用该方法的实例,单独调用时需注意绑定this:javascript
运行
const user = new User("张三"); const sayHello = user.sayHello; sayHello(); // this为undefined(严格模式),报错 sayHello.call(user); // 正确:绑定this
-
七、总结:核心知识点回顾
- 基础层:对象字面量是创建单个对象的最佳选择,简洁高效;
- 复用层:工厂函数适合简单批量创建,构造函数 / Class 适合复杂对象 + 类型区分;
- 灵活层 :
Object.create()控原型,Object.assign()/ 展开运算符控属性; - 核心原则:按需选择方法(简单场景用字面量,复杂场景用 Class,灵活扩展用展开运算符),优先使用浅拷贝(深拷贝按需使用)。
JavaScript 的对象创建方法,从简单到复杂,从基础到进阶,本质是 "复用性" 和 "灵活性" 的平衡。掌握不同方法的适用场景,不仅能写出更简洁、高效的代码,还能加深对 JS 原型链、面向对象的理解 ------ 这也是从 "入门级开发者" 到 "中高级开发者" 的关键一步。
最后用一句话总结:对象创建的核心是 "场景匹配",选对方法,既能减少冗余,又能提升代码可维护性。