理解 JavaScript 中构造方法的核心作用与工作机制
掌握两种主要的构造方法定义方式:函数构造器与类构造器
学会使用 new 关键字创建对象实例
了解 Object.create()、工厂函数等替代对象创建方式及其适用场景
掌握为构造方法设置默认参数、使用原型共享方法、实现继承等高级技巧
在 JavaScript 中,构造方法是一种特殊函数,用于创建并初始化对象。它通过 new 关键字调用,自动完成以下操作:
创建一个新空对象
将 this 绑定到该新对象
执行构造函数体内的代码(通常用于设置属性)
隐式返回新创建的对象
构造方法使得我们可以批量创建结构一致但数据不同的对象实例。
这是早期 JavaScript 实现面向对象的主要方式:
function Car(brand, model, year) {
this.brand = brand;
this.model = model;
this.year = year;
this.getInfo = function() {
return `${this.year} 年款 ${this.brand} ${this.model}`;
};
}
const myCar = new Car("丰田", "凯美瑞", 2020);
console.log(myCar.getInfo()); // 输出:2020 年款 丰田 凯美瑞特点:
函数名首字母通常大写(如
Car),表示它是构造函数使用
this为新对象添加属性和方法每次创建实例时,方法都会被重新定义(内存效率较低)
ES6 引入了更清晰的 class 语法:
class Car {
constructor(brand, model, year) {
this.brand = brand;
this.model = model;
this.year = year;
}
getInfo() {
return `${this.year} 年款 ${this.brand} ${this.model}`;
}
}
const myCar = new Car("本田", "思域", 2022);
console.log(myCar.getInfo()); // 输出:2022 年款 本田 思域优势:
语法更简洁、结构更清晰
方法自动绑定到原型(prototype),节省内存
更接近传统 OOP 语言风格,易于理解
new 关键字无论使用函数还是类,new 都是创建实例的关键:
// 使用函数构造器
function Student(name, age) {
this.name = name;
this.age = age;
}
const stu1 = new Student("李明", 21);
// 使用类构造器
class Teacher {
constructor(name, subject) {
this.name = name;
this.subject = subject;
}
}
const tea1 = new Teacher("王老师", "数学");
console.log(stu1); // Student { name: '李明', age: 21 }
console.log(tea1); // Teacher { name: '王老师', subject: '数学' }new 的核心作用是将普通函数 / 类转换为对象生成器。
Object.create()基于原型的复制
该方法不调用构造函数,而是直接以一个对象为原型创建新对象:
const baseUser = {
role: "user",
login() {
console.log(`${this.name} 已登录`);
}
};
const user1 = Object.create(baseUser);
user1.name = "张三";
user1.login(); // 输出:张三 已登录
console.log(user1.role); // 输出:user(从原型继承)适用于无需初始化逻辑、只需继承已有对象行为的场景。
返回对象的普通函数,无需 new:
function createUser(name, email) {
return {
name: name,
email: email,
greet() {
console.log(`你好,${this.name}!`);
}
};
}
const user1 = createUser("赵六", "zhao@example.com");
user1.greet(); // 输出:你好,赵六!优点:
避免
this绑定问题可封装私有变量(通过闭包)
更灵活,可返回不同类型的对象
为参数提供默认值,增强健壮性:
function Person(name = "匿名", age = 0) {
this.name = name;
this.age = age;
}
const p1 = new Person("刘洋", 28); // 正常传参
const p2 = new Person("陈晨"); // age 使用默认值 0
const p3 = new Person(); // 全部使用默认值
console.log(p1); // Person { name: '刘洋', age: 28 }
console.log(p2); // Person { name: '陈晨', age: 0 }
console.log(p3); // Person { name: '匿名', age: 0 }优化内存
避免每次创建实例都重复定义方法:
function Animal(species) {
this.species = species;
}
// 方法定义在原型上,所有实例共享
Animal.prototype.speak = function() {
console.log(`这是一只 ${this.species}`);
};
const cat = new Animal("猫");
const dog = new Animal("狗");
cat.speak(); // 输出:这是一只 猫
dog.speak(); // 输出:这是一只 狗
// 验证是否共享同一个方法
console.log(cat.speak === dog.speak); // true这是函数构造器中提升性能的关键技巧。
使用 extends 和 super 实现类继承:
class Vehicle {
constructor(type) {
this.type = type;
}
start() {
console.log(`${this.type} 启动了`);
}
}
class Bike extends Vehicle {
constructor(brand, color) {
super("自行车"); // 调用父类构造函数
this.brand = brand;
this.color = color;
}
describe() {
return `${this.color} 的 ${this.brand} 自行车`;
}
}
const myBike = new Bike("捷安特", "蓝色");
myBike.start(); // 输出:自行车 启动了
console.log(myBike.describe()); // 输出:蓝色 的 捷安特 自行车构造方法是创建和初始化对象的核心机制
ES6 的 class 语法是对传统函数构造器的语法糖,更易读
new 关键字负责实例化过程,绑定 this 并返回对象
方法应尽量定义在原型上(函数构造器)或类体内(ES6 类),避免重复创建
工厂函数和 Object.create() 提供了不依赖 new 的替代方案
默认参数、继承、原型共享等技巧可显著提升代码质量与性能
如果忘记在调用构造函数时使用 new(如 let obj = Person("张三", 20)),会发生什么?如何避免此类错误?
在函数构造器中,为什么推荐将方法定义在 prototype 上而不是构造函数内部?请从内存和性能角度分析。
比较工厂函数与类构造器的优缺点,在什么场景下应优先选择工厂函数?