JavaScript通过原型对象实现属性和方法共享,构造函数的prototype添加的成员被所有实例共用;访问时按实例→__proto__→Object.prototype顺序查找;避免在prototype上定义引用类型共享属性,ES6 class是原型的语法糖。

在 JavaScript 中,通过原型对象(prototype)实现属性和方法的共享,核心是让多个实例对象共用同一个原型对象上的属性和方法,从而节省内存、避免重复定义。
构造函数 + prototype 添加共享成员
给构造函数的 prototype 对象添加属性或方法,所有通过该构造函数创建的实例都能访问到,且指向同一份定义。
例如:
function Person(name) {
this.name = name; // 实例自有属性
}
Person.prototype.sayHello = function() {
console.log('Hello, I am ' + this.name);
};
Person.prototype.species = 'Homo sapiens'; // 共享的属性(一般不推荐共享可变数据)
const p1 = new Person('Alice');
const p2 = new Person('Bob');
p1.sayHello(); // Hello, I am Alice
p2.sayHello(); // Hello, I am Bob
console.log(p1.species === p2.species); // true —— 同一个值
理解原型链查找机制
当访问实例的属性或方法时,JavaScript 引擎会按以下顺序查找:
立即学习“Java免费学习笔记(深入)”;
- 先在实例自身上找(own property)
- 找不到,就沿着 __proto__(即构造函数的 prototype)向上查找
- 直到找到,或到达 Object.prototype(最终返回 undefined)
这意味着:实例不会复制原型上的方法,只是“链接”过去调用;修改原型会影响所有已存在和将创建的实例(除非被实例自身同名属性遮蔽)。
避免在 prototype 上定义引用类型共享属性
如果在 prototype 上直接定义数组、对象等引用类型,它们会被所有实例共享——修改一个实例会影响其他实例,容易引发意外。
错误示例:
Person.prototype.hobbies = []; // ❌ 危险!所有实例共用一个数组
p1.hobbies.push('reading');
console.log(p2.hobbies); // ['reading'] —— p2 也被影响了
正确做法:在构造函数内部初始化实例专属的引用类型:
function Person(name) {
this.name = name;
this.hobbies = []; // ✅ 每个实例独立拥有
}
Person.prototype.addHobby = function(hobby) {
this.hobbies.push(hobby); // 方法仍可共享
};
ES6 class 语法背后的原型本质
class 是语法糖,其方法默认定义在原型上,天然支持共享:
class Animal {
constructor(name) {
this.name = name;
}
speak() { // 等价于 Animal.prototype.speak = ...
console.log(this.name + ' makes a sound');
}
}
const a1 = new Animal('Dog');
const a2 = new Animal('Cat');
console.log(a1.speak === a2.speak); // true
注意:class 中定义的字段(如 prop = value)属于实例自身,不是共享的;静态方法(static)则挂载在类本身,也不通过原型链继承给实例。


















