实例属性属对象自身,原型属性属构造函数prototype;前者独立存储、修改互不影响,后者共享内存、修改影响所有实例;可用hasownproperty()、in操作符和object.getprototypeof()判断归属。

区分属性归属,关键看属性定义的位置和访问时的查找路径。实例对象自身的属性和原型对象上的属性,虽然都能被实例访问,但内存分配、修改影响范围、以及查找优先级完全不同。
实例对象自己的属性(实例属性)
在构造函数内部用 this 显式赋值的属性,属于该实例独有。
- 每次 new 都会为每个实例开辟独立内存空间,互不影响
- 修改一个实例的该属性,不会波及其他实例
- 即使原型上存在同名属性,实例属性也会优先被访问(屏蔽原型属性)
例如:
function Person(name) {
this.name = name; // 实例属性
this.hobbies = ['reading'];
}
const p1 = new Person('Alice');
const p2 = new Person('Bob');
p1.hobbies.push('coding');
console.log(p1.hobbies); // ['reading', 'coding']
console.log(p2.hobbies); // ['reading'] ← 不受影响
原型对象上的属性(原型属性)
通过 Constructor.prototype 添加的属性或方法,由所有实例共享。
- 只在内存中存一份,节省资源,适合方法或不变量
- 修改原型上的引用类型属性(如数组、对象),会影响所有实例
- 实例自身没有该属性时,才会沿 __proto__ 向上查找原型
例如:
Person.prototype.species = 'Homo sapiens';
Person.prototype.sayHello = function() {
return `Hello, I'm ${this.name}`;
};
console.log(p1.species === p2.species); // true
console.log(p1.sayHello === p2.sayHello); // true ← 同一函数引用
如何判断某个属性属于哪一层
可以用三个常用方式验证归属:
- hasOwnProperty():返回 true 表示是实例自身属性
- in 操作符:只要能在整个原型链上找到就返回 true
- Object.getPrototypeOf(obj) === Constructor.prototype:确认该属性是否定义在原型上
示例:
p1.name; // 'Alice' → hasOwnProperty('name') 为 true
p1.species; // 'Homo sapiens' → hasOwnProperty('species') 为 false,但 'species' in p1 为 true
Object.getPrototypeOf(p1) === Person.prototype; // true
常见误区提醒
不要在原型上直接定义可变引用类型(如数组、对象)作为“默认值”,否则多个实例会意外共享同一份数据。需要在构造函数中初始化才安全。
比如:避免 Person.prototype.tags = [];,而应写成 this.tags = []; 放在构造函数内。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











