javascript 中的原型对象和实例通过 [[prototype]] 属性建立关联,实例在访问自身不存在的属性时会自动沿着这条链向上查找。具体做法是确保构造函数(如 person)的 prototype 属性指向一个共享的原型对象,而其实例(如 new person())的 __proto__ 或 object.getprototypeof() 也指向该对象。这样不仅实现了方法复用,还保证了数据隔离。

如何通过构造函数设置原型关系
使用构造函数创建实例时,JavaScript 引擎会自动将构造函数的 prototype 属性赋值给新对象的内部原型链接。这意味着所有由同一构造函数创建的实例都共享同一个原型对象。开发者可以通过修改构造函数的 prototype 来为所有实例添加公共方法或属性,而不需要在每个实例中重复定义。

function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
return 'Hello, ' + this.name;
};
const alice = new Person('Alice');
console.log(alice.sayHello()); // "Hello, Alice"
console.log(alice.__proto__ === Person.prototype); // true
上述代码展示了标准的原型链设置方式。alice 实例拥有自己的 name 属性,而其 sayHello 方法则来自 Person.prototype。这种机制确保了内存的高效利用,因为方法只存在于原型对象中,而非每个实例中。
如何验证实例与原型的关系
验证实例与原型的关系主要依赖两个操作符和方法:instanceof 用于检查实例是否属于某个构造函数的原型链,isPrototypeOf() 用于检查一个对象是否存在于另一个对象的原型链上。这些工具帮助开发者确认对象继承关系的正确性,特别是在处理复杂的多级继承或自定义类结构时。

function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
const dog = new Dog();
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
console.log(Animal.prototype.isPrototypeOf(dog)); // true
console.log(Dog.prototype.isPrototypeOf(dog)); // true
这段代码演示了原型链的传递性。Dog 的原型被设置为 Animal 的实例,因此 dog 既属于 Dog 也属于 Animal。通过 isPrototypeOf 可以明确看到 Animal.prototype 和 Dog.prototype 都在 dog 的原型链上。这种关系是 JavaScript 实现面向对象编程的核心基础。
当原型对象被重新赋值时会发生什么
如果直接替换构造函数的 prototype 属性,之前已经创建的实例不会受到影响,因为它们仍然指向旧的原型对象。只有在新赋值之后创建的实例才会连接到新的原型对象。这种行为可能导致意外,特别是当开发者期望所有实例都能立即获得新方法时。正确的做法是在原型对象上直接添加属性,或者在替换后手动更新现有实例的原型链接。
function Cat() {}
Cat.prototype.meow = function() { return 'Meow'; };
const oldCat = new Cat();
// 错误做法:直接替换 prototype
Cat.prototype = { purr: function() { return 'Purr'; } };
const newCat = new Cat();
console.log(oldCat.meow()); // "Meow" (旧原型)
console.log(oldCat.purr); // undefined (不在旧原型上)
console.log(newCat.purr()); // "Purr" (新原型)
console.log(newCat.meow); // undefined (不在新原型上)
此示例清晰地展示了原型替换的后果。oldCat 依然保留对原始原型对象的引用,因此能调用 meow 但无法访问 purr。而 newCat 则连接到新的原型对象,只能调用 purr。为了避免这种不一致,建议在原型对象上直接扩展属性,而不是替换整个原型对象。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











