类方法在原型上、属性在实例上,由JS引擎按规则分配;实例属性用hasOwnProperty()和getOwnPropertyNames()检测,方法定义在prototype上且共享,类字段属实例,static成员属类本身,__proto__指向原型链。

类方法在原型上、属性在实例上,这种分布不是随意安排的,而是由 JavaScript 引擎在内存中按规则分配的。识别它的关键,在于理解“谁拥有它”和“怎么查得到它”这两个物理事实。
看属性是否出现在实例自身上
用 Object.hasOwnProperty() 最直接:
-
obj.hasOwnProperty('name')返回 true → name 是实例属性,存在 obj 对象自身内存块里 -
obj.hasOwnProperty('toString')返回 false → toString 不在实例上,它在原型链某处
再配合 Object.getOwnPropertyNames(obj),它只列出实例自己拥有的属性名(不含原型上的),能一眼看出哪些是真正“属于这个对象”的数据。
查方法定义位置:prototype 上才有共享逻辑
所有在 class 内部声明的普通方法(如 render() { })、或显式挂到 ClassName.prototype.xxx = 的函数,都存放在构造函数的 prototype 对象中:
-
MyClass.prototype.render存在 → render 是原型方法 -
obj.render === MyClass.prototype.render为 true → 当前调用的就是原型上的那个函数 -
MyClass.prototype.hasOwnProperty('render')为 true → 它确实在 prototype 自身上
这类方法在内存中只有一份,所有实例共用,不随 new 多少次而复制。
区分类字段(public field)和 static 成员的归属
类体内的 count = 0 看似写在类里,但它本质是“每次 new 时自动执行 this.count = 0”,所以:
- 每个实例的
count都独立存在自己的内存空间里 -
MyClass.prototype.count是 undefined -
MyClass.count也是 undefined —— 它既不在原型也不在类本身,只在实例上
而 static version = '1.2' 是另一回事:它直接挂在 MyClass 函数对象上,属于类本身,和实例、原型都无关。
用 __proto__ 和 constructor 追踪原型链路径
每个实例都有一个 __proto__,它指向其构造函数的 prototype:
-
obj.__proto__ === MyClass.prototype→ 确认原型链第一跳位置 -
obj.__proto__.constructor === MyClass→ 反向验证构造关系 - 顺着
obj.__proto__.__proto__往上,还能看到Object.prototype,这就是完整查找路径
属性访问时引擎就按这条链一层层找,找到第一个匹配就停——这也解释了为什么实例属性总能“遮蔽”原型上的同名属性。










