我正在阅读 ES6 课程,据说它只是语法糖。那为什么在
Object.keys
上调用 Class.prototype
没有列出类的方法呢?
class Class { whoami() { return "class"; } }
function Proto() {}
Proto.prototype.whoami = function () { return "proto"; }
console.log(Class.prototype); // { constructor: f() {}, whoami: f() {} }
console.log(Proto.prototype); // { constructor: f() {}, whoami: f() {} }
console.log(Object.keys(Class.prototype)); // [] <--- WHY ???
console.log(Object.keys(Proto.prototype)); // ["whoami"]
您观察到的
Object.keys(Class.prototype)
和 Object.keys(Proto.prototype)
之间的差异与类方法在 ES6 类中的定义和存储方式(与传统的基于原型的对象相比)有关。
在您的示例中,
Class
是一个 ES6 类,Proto 是具有手动定义原型的传统构造函数。
当您使用速记语法(如
whoami() { return "class"; }
)在 ES6 类中定义方法时,该方法将添加到类原型中。但是,默认情况下这些方法是不可枚举的,这意味着当您使用 Object.keys()
迭代对象的属性时,它们不会显示。
这是为了模仿其他编程语言(如 Java)中类方法的行为而做出的设计选择。在大多数情况下,您不希望这些内部方法在迭代对象的键时可见。
如果您想让方法可枚举(因此出现在
Object.keys(Class.prototype)
中),您可以显式地将方法的属性 descriptor
设置为可枚举
当您在构造函数的原型上手动定义方法(如
Proto.prototype.whoami = function () { return "proto"; }
)时,该方法将添加到原型中,且 enumerable
属性默认设置为 true。这就是为什么您会看到 Object.keys(Proto.prototype)
中的方法。