构造函数必须首字母大写,且须用 new 调用;否则 this 指向错误,易污染全局或报错,影响可读性与协作。

用 function 定义构造函数时必须首字母大写
JavaScript 中没有原生的“类声明即构造”机制(ES6 class 是语法糖),传统构造函数本质就是普通函数,但调用方式和语义不同。关键在于:必须用 new 调用,且函数名习惯性首字母大写,否则容易误当普通函数执行,导致 this 指向错误。
- 不加
new调用:this指向全局对象(非严格模式)或undefined(严格模式),属性会挂到全局或报错 - 忘记首字母大写,团队协作或阅读时无法快速识别其构造意图
- 构造函数内部通常用
this.xxx = xxx初始化实例属性,不返回值(或显式返回对象)
function Person(name, age) {
this.name = name;
this.age = age;
}
const p1 = new Person('Alice', 30); // ✅ 正确
const p2 = Person('Bob', 25); // ❌ this 指向错误,可能污染全局
class 语法定义构造函数更安全但仍有陷阱
class 是 ES6 引入的构造函数封装,底层仍基于原型链,但强制要求用 new 调用,避免了手写 function 的常见疏漏。不过它不是完全的“类”,比如不能在类体中直接写实例属性(除非用字段声明语法,且需注意兼容性)。
-
constructor()方法是唯一初始化逻辑入口,省略时会隐式添加空构造器 - 类方法默认不可枚举,而手动在
prototype上挂载的函数是可枚举的(影响for...in) - 字段声明(如
name = 'default')在构造器执行前初始化,但仅在现代引擎(Chrome 72+、Node.js 12.4+)支持,旧环境需 Babel 转译
class Car {
brand = 'Unknown'; // 字段声明(非所有环境支持)
constructor(brand, year) {
this.brand = brand;
this.year = year;
}
}
const c1 = new Car('Tesla', 2023); // ✅ 必须 new,否则 TypeError
不用构造函数也能创建对象:字面量与 Object.create()
并非所有对象都需要构造函数。简单、一次性、无复用需求的对象,用字面量最直接;需要精确控制原型链(比如继承某个特定对象但不调用其构造器),Object.create() 更合适。
- 对象字面量:
{}创建的对象原型是Object.prototype,适合配置项、临时数据容器 -
Object.create(proto)创建的对象,其[[Prototype]]直接设为proto,不执行任何构造逻辑,适合“纯原型委托”场景 - 误用
Object.create(null)会得到一个无原型的对象,hasOwnProperty等方法不可用,需自行处理
const config = { timeout: 5000, retries: 3 }; // 字面量,够用就别造轮子
const animal = { eats: true };
const dog = Object.create(animal);
dog.barks = true;
console.log(dog.eats); // true —— 原型链查找
构造函数的 prototype 属性容易被忽略的细节
每个函数都有 prototype 属性(仅函数有),它是用于设置将来通过该函数构造出的实例的原型对象。这个属性名容易让人误解为“实例的原型”,其实它是“构造器的原型对象”,而实例的真正原型是 constructor.prototype。
立即学习“Java免费学习笔记(深入)”;
- 给
MyConstructor.prototype添加方法,所有实例都能共享该方法,节省内存 - 修改已存在实例的
__proto__不会影响其他实例,但会破坏原型链一致性,不推荐 - ES6 后应优先使用
Object.getPrototypeOf(obj)获取实例原型,而非访问非标准的__proto__
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
const a = new Animal('Lion');
console.log(Object.getPrototypeOf(a) === Animal.prototype); // true
构造函数的核心不在“怎么写”,而在“谁来负责初始化”和“原型链是否可控”。手写 function 最灵活但易错,class 更规范但隐藏了原型细节,字面量和 Object.create() 则绕开了构造逻辑本身——选哪个,取决于你是否真需要“批量生成带共同行为的对象”。











