javascript 中构造函数通过其 prototype 属性引用原型对象。在定义构造函数时,引擎会自动创建一个原型对象,并将构造函数的 prototype 指向该对象;实例化时,实例的 [[prototype]](即 __proto__)会被设置为构造函数的 prototype,从而建立关联。

构造函数 prototype 属性的初始化机制是什么
当使用 function 关键字声明构造函数时,JavaScript 引擎会立即为该函数对象分配一个默认的 prototype 属性。这个属性指向一个空的对象实例,该对象默认包含一个 constructor 属性,指回构造函数本身。这是原型链建立的起点。

function Person(name) {
this.name = name;
}
// 此时 Person.prototype 已经存在并指向一个对象
console.log(Person.prototype.constructor === Person); // true
const p1 = new Person('Alice');
// p1 的内部 [[Prototype]] 指向 Person.prototype
console.log(p1.__proto__ === Person.prototype); // true
上述代码展示了标准流程。创建 Person 函数后,Person.prototype 自动指向一个对象。实例 p1 通过 new 操作符创建,其内部原型链接向 Person.prototype。这种引用是单向的:构造函数持有对原型对象的引用,而实例通过原型链间接访问原型对象的方法。
修改 prototype 属性对已有实例的影响如何
如果在实例化之后修改构造函数的 prototype 属性,新创建的实例将指向新的原型对象,但已存在的实例仍然指向旧的原型对象。这是因为 new 操作符在创建实例时,会将实例的 [[Prototype]] 绑定到当时 prototype 属性所指向的对象地址。

function Animal(type) {
this.type = type;
}
const dogProto = { speak: 'Woof' };
Animal.prototype = dogProto;
const pet1 = new Animal('Dog');
// 修改 prototype 指向新对象
Animal.prototype = { speak: 'Meow' };
const pet2 = new Animal('Cat');
console.log(pet1.speak); // 'Woof'
console.log(pet2.speak); // 'Meow'
console.log(pet1.__proto__ === Animal.prototype); // false
console.log(pet2.__proto__ === Animal.prototype); // true
这段代码验证了引用关系。首先将 Animal.prototype 指向 dogProto,创建 pet1,此时 pet1 的原型指向 dogProto。随后将 Animal.prototype 重新赋值为一个新对象,再创建 pet2。pet2 的原型指向新对象,而 pet1 仍保留对旧对象的引用。这证明了构造函数通过 prototype 属性动态引用原型对象,且实例一旦创建,其原型链接即固定。
直接赋值 prototype 会导致 constructor 丢失吗
是的,如果直接将 prototype 属性赋值为一个普通对象字面量,原有的 constructor 属性会被覆盖,导致原型对象失去对构造函数的引用。需要手动重置 constructor 以恢复常规行为。
function Vehicle(model) {
this.model = model;
}
// 错误做法:直接替换 prototype
Vehicle.prototype = {
drive: function() {
console.log('Driving');
}
};
const v1 = new Vehicle('Sedan');
console.log(v1.constructor === Vehicle); // false
console.log(v1.constructor === Object); // true
// 正确做法:手动修复 constructor
Vehicle.prototype.constructor = Vehicle;
在上面的代码中,直接给 Vehicle.prototype 赋值对象字面量会创建一个新对象,该对象没有 constructor 属性。因此 v1.constructor 沿着原型链向上查找,最终找到 Object.prototype.constructor,结果为 Object。通过显式设置 Vehicle.prototype.constructor = Vehicle,可以恢复正确的引用关系。这说明了构造函数与原型对象之间的双向约定:prototype 引用原型,原型中的 constructor 引用构造函数。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











