构造函数需用 new 调用以创建实例,内部不可自行 new 否则导致递归溢出;其本质是普通函数,new 会自动创建空对象、绑定 this、执行初始化并默认返回 this。

在 JavaScript 中,构造函数本身并不使用 new 创建对象;而是你调用构造函数时,**用 new 关键字来调用它**,从而创建新对象。构造函数内部不需要、也不应该自己用 new 去创建自身实例——那会导致无限递归或逻辑错误。
构造函数的作用和 new 的配合机制
构造函数本质是一个普通函数,它的特殊性只体现在被 new 调用时的执行过程:
- 自动创建一个空对象(即即将返回的实例)
- 将该对象绑定为函数内部的
this - 执行函数体中的代码(通常用来初始化属性)
-
默认返回这个
this对象(除非显式返回另一个非 null 对象)
✅ 正确写法示例:
function Person(name, age) {
this.name = name; // 初始化实例属性
this.age = age;
}
const alice = new Person('Alice', 30); // ✅ 用 new 调用构造函数
console.log(alice.name); // 'Alice'
为什么构造函数里不能自己用 new?
如果在构造函数内部又调用 new Person(...),会出现以下问题:
- 无限递归调用,很快触发栈溢出(
RangeError: Maximum call stack size exceeded) - 违背构造函数的设计意图:它负责初始化当前实例,不是“生成另一个实例”
- 返回值混乱:可能覆盖原本要返回的
this
❌ 错误写法示例:
function BadPerson(name) {
this.name = name;
return new BadPerson(name + '_clone'); // ❌ 危险!递归创建
}
想在构造函数中复用其他构造逻辑?用组合或工厂模式
如果需要基于已有构造函数创建多个相关对象,推荐以下安全方式:
-
组合调用:在构造函数中调用其他构造函数并手动绑定
this(如OtherConstructor.call(this, ...)) -
工厂函数封装:把
new调用封装在普通函数里,更灵活可控 -
ES6 类继承:用
extends和super()复用父类初始化逻辑
例如工厂模式:
function createPerson(name, age) {
return new Person(name, age); // ✅ new 在外部可控位置调用
}
const bob = createPerson('Bob', 25);
小提醒:首字母大写是约定,不是语法强制
虽然习惯上把构造函数名首字母大写(如 Person),但 JavaScript 并不检查这点。如果忘记用 new 调用,this 会指向全局对象(非严格模式)或 undefined(严格模式),导致静默错误。
为避免疏漏,可加运行时检查:
function SafePerson(name) {
if (!(this instanceof SafePerson)) {
return new SafePerson(name); // 自动补 new
}
this.name = name;
}
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











