通过实例对象的 __proto__ 属性可以访问其原型对象,该属性指向创建该实例的构造函数的 prototype 属性。在 javascript 中,每个对象都有一个内部链接指向另一个对象,即它的原型,而 __proto__ 是大多数浏览器提供的对这一内部链接 [[prototype]] 的访问器。要获取一个对象的原型,直接读取其 __proto__ 即可;若要修改原型,则需使用 object.setprototypeof() 或 object.create(),因为直接赋值给 __proto__ 虽然有效但性能较差且不被推荐用于生产环境。

构造函数与原型的关系是什么
构造函数的 prototype 属性指向原型对象,而实例对象的 __proto__ 也指向同一个原型对象。这种关系构成了原型链的基础。当访问实例的一个属性时,如果实例本身没有该属性,JavaScript 引擎会沿着 __proto__ 指向的原型对象继续查找,直到找到该属性或到达原型链末端(null)。

function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return `Hello, my name is ${this.name}`;
};
const alice = new Person('Alice');
// 访问原型对象
console.log(alice.__proto__ === Person.prototype); // true
// 通过原型调用方法
console.log(alice.greet()); // Hello, my name is Alice
// 查看原型链
console.log(Object.getPrototypeOf(alice)); // { greet: [Function] }如何安全地操作原型链
虽然可以直接读写 __proto__,但在现代开发中更推荐使用 Object.getPrototypeOf() 来获取原型,以及 Object.setPrototypeOf() 来设置原型。这些方法是 ES6 标准的一部分,行为更加明确和稳定。此外,Object.create(proto) 可以用于创建一个以指定对象为原型的新对象,这在需要自定义原型关系的场景中非常有用。
立即学习“Java免费学习笔记(深入)”;

// 获取原型
const proto = Object.getPrototypeOf(alice);
console.log(proto === Person.prototype); // true
// 设置原型
const bob = {};
Object.setPrototypeOf(bob, Person.prototype);
bob.name = 'Bob';
console.log(bob.greet()); // Hello, my name is Bob
// 创建新对象并指定原型
const charlie = Object.create(Person.prototype);
charlie.name = 'Charlie';
console.log(charlie.greet()); // Hello, my name is Charlie
// 检查原型链
console.log(Object.getPrototypeOf(charlie) === Person.prototype); // true
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype)); // null原型链断裂时会发生什么
当原型链被意外修改或断裂时,对象可能无法正确继承其应有的属性和方法。例如,如果将构造函数的 prototype 重新赋值为一个新对象,而未保留原有的方法和属性,那么之前创建的实例将无法访问这些新方法,除非它们也被添加到新的原型对象中。此外,如果手动设置某个实例的 __proto__ 为一个不相关的对象,可能会导致类型检查失败或方法调用错误。因此,在修改原型链时应格外小心,确保所有相关对象都能正确访问所需的属性和方法。


















