javascript 中实例读取原型对象属性依靠的是原型链查找机制,当访问实例的一个属性时,引擎会先在实例自身查找,若未找到则沿着 __proto__ 指向的原型对象继续向上搜索,直到找到该属性或到达原型链顶端。这种机制允许所有实例共享原型上的属性和方法,从而实现代码复用和继承效果。

实例创建后如何关联到原型对象
在 JavaScript 中,每个函数都有一个 prototype 属性,它指向一个原型对象。当使用 new 关键字调用构造函数时,新创建的实例会自动获得一个内部链接(即 [[Prototype]]),该链接指向构造函数的 prototype 属性所指向的对象。这意味着实例可以通过这个链接访问原型对象上的所有属性和方法。

function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return `Hello, my name is ${this.name}`;
};
const person1 = new Person('Alice');
console.log(person1.greet()); // Hello, my name is Alice
console.log(person1.hasOwnProperty('greet')); // false
console.log('greet' in person1); // true
上述代码展示了如何通过构造函数创建实例,并验证实例是否拥有原型上的属性。hasOwnProperty 方法用于检查属性是否存在于实例自身,而 in 运算符则检查属性是否存在于实例及其原型链上。
原型链查找的具体过程是怎样的
当访问实例的一个属性时,JavaScript 引擎首先会在实例自身查找该属性。如果找到,则返回该属性的值;如果未找到,则引擎会沿着 __proto__ 指向的原型对象继续查找。如果在原型对象中找到该属性,则返回其值;如果仍未找到,则继续沿着原型对象的原型链向上查找,直到到达原型链的顶端(即 Object.prototype)。如果在整个原型链上都未找到该属性,则返回 undefined。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型

function Animal(type) {
this.type = type;
}
Animal.prototype.speak = function() {
return `${this.type} makes a sound.`;
};
function Dog(breed) {
Animal.call(this, 'Dog');
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
return 'Woof!';
};
const dog1 = new Dog('Labrador');
console.log(dog1.speak()); // Dog makes a sound.
console.log(dog1.bark()); // Woof!
console.log(dog1.hasOwnProperty('speak')); // false
console.log('speak' in dog1); // true
console.log(dog1.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
console.log(Animal.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
上述代码展示了原型链查找的具体过程。通过 Object.create 方法将 Dog 的原型设置为 Animal 的原型,从而建立了原型链关系。实例 dog1 可以访问 Dog、Animal 和 Object 原型上的属性和方法。
修改原型对象会影响已创建的实例吗
是的,修改原型对象会影响所有已创建的实例。因为实例是通过原型链访问原型对象上的属性和方法的,所以任何对原型对象的修改都会立即反映在所有实例上。然而,需要注意的是,如果在实例上定义了与原型同名的属性,则实例自身的属性会屏蔽原型上的同名属性,这种现象称为属性遮蔽。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
return `Hello, my name is ${this.name}`;
};
const person1 = new Person('Alice');
console.log(person1.greet()); // Hello, my name is Alice
Person.prototype.greet = function() {
return `Hi, my name is ${this.name}`;
};
console.log(person1.greet()); // Hi, my name is Alice
person1.greet = function() {
return `Hey, my name is ${this.name}`;
};
console.log(person1.greet()); // Hey, my name is Alice
console.log(person1.hasOwnProperty('greet')); // true
上述代码展示了修改原型对象对已创建实例的影响。首先,我们修改了 Person.prototype.greet 方法,发现 person1 的 greet 方法也随之改变。然后,我们在 person1 实例上定义了 greet 方法,此时 person1 的 greet 方法被实例自身的属性遮蔽,不再访问原型上的方法。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










