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。这种引用是单向的:构造函数持有对原型对象的引用,而实例通过原型链间接访问原型对象的方法。
立即学习“Java免费学习笔记(深入)”;
修改 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 引用构造函数。


















