es6类中所有非静态方法都挂载在类的prototype上:babel编译后转为person.prototype.say=function(){};运行时person.prototype包含say,实例自身无该方法;static方法则直接挂载在类函数对象上。

直接查看编译后的 JavaScript 代码就能证实:ES6 类中所有非静态方法(即没加 static 的方法)确实都挂载在类的 prototype 上。
用 Babel 编译后观察生成代码
Babel 是最常用的 ES6+ 转译工具,它把 class 明确展开为等效的函数+原型赋值形式:
- 类声明
class Person { say() { return 'hi'; } }编译后变成:function Person() { }Person.prototype.say = function() { return 'hi'; }; - 构造函数体(
constructor)里的语句被移到函数体内;
其余方法全部转为Class.prototype.xxx = function() {...}形式。 - 你可以用 Babel REPL 粘贴类代码,实时看输出,一目了然。
运行时检查 prototype 属性
不依赖编译器,也能在浏览器或 Node.js 中直接验证:
- 定义类后,执行
console.log(Person.prototype),能看到say、toString等方法列在其中; - 用
Object.getOwnPropertyNames(Person.prototype)获取所有自有属性名,非静态方法名会出现在结果里; - 而
Object.getOwnPropertyNames(new Person())返回的只是实例自身属性(如name),不含方法名——说明方法不在实例上。
对比 static 方法的位置差异
这是辅助验证的关键对照:
-
static walk() {}编译后变成Person.walk = function() {},直接挂在函数对象本身; - 所以
Person.walk可调,new Person().walk报错; - 而非静态方法如
say()在Person.prototype上,所以所有实例共享,且可继承。
用 instanceof 和原型链反向印证
既然方法在 prototype 上,那原型链必然连通:
- 创建实例
const p = new Person(); -
p.__proto__ === Person.prototype返回true; -
p.say()能执行,是因为 JS 引擎沿p → p.__proto__ → p.__proto__.constructor查找,最终在Person.prototype找到say。











