ES6类方法默认不可枚举,因其在property descriptor层面显式设为enumerable: false,挂载于prototype上;Object.keys()仅返回自有且可枚举的字符串键,故不包含类方法。

ES6 类方法默认不可枚举,这个特性是在属性描述符(property descriptor)层面直接设定的,不是靠运行时拦截或语法限制实现的。
类方法被定义在 prototype 上,且 enumerable 为 false
当你写一个类:
class Person {constructor(name) { this.name = name; }
sayHello() { return `Hi, ${this.name}`; }
}
等价于在 Person.prototype 上通过 Object.defineProperty 添加方法,且显式设定了 enumerable: false。Babel 转译后的关键逻辑就是调用 _defineProperties 函数,它内部对每个方法 descriptor 都做了如下处理:
descriptor.enumerable = descriptor.enumerable || falseObject.defineProperty(target, key, descriptor)
也就是说,类中声明的每个实例方法,最终都以不可枚举方式挂载到原型对象上。
立即学习“Java免费学习笔记(深入)”;
Object.keys() 只遍历自有且可枚举的字符串键
Object.keys() 的行为是严格限定的:它只返回对象自身(不包括原型链)、属性键为字符串、且 enumerable === true 的属性名。
因此:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
-
Object.keys(Person.prototype)返回空数组,因为sayHello是不可枚举的 -
for...in也跳过它(因依赖enumerable标志) - 但
Person.prototype.sayHello仍可正常调用——不可枚举 ≠ 不可用
对比传统构造函数写法,凸显设计意图
如果手动给原型赋值:
function Person(name) { this.name = name; }Person.prototype.sayHello = function() { return `Hi, ${this.name}`; };
此时 sayHello 是可枚举的(因直接赋值默认 enumerable: true),Object.keys(Person.prototype) 就会包含它。
ES6 类刻意避免这种“污染”,让原型更干净——这是语言设计上对面向对象惯例的靠拢:方法是行为契约,不是数据字段,不应出现在常规属性遍历中。
静态方法同理,只是挂载位置不同
类中的 static 方法被定义在构造函数本身(即 Person 函数对象)上,同样使用 Object.defineProperty 设置 enumerable: false。
所以:
-
Object.keys(Person)不会返回静态方法名 -
Person.isAdult依然可调用,只是不参与枚举遍历
不复杂但容易忽略

















