【发布时间】:2017-05-02 12:47:57
【问题描述】:
在 ES6 中添加的 JavaScript 的 class syntax 显然使 extend null 合法:
class foo extends null {}
一些谷歌搜索显示was suggested on ES Discuss 这样的声明是错误的;然而,其他评论者认为他们是合法的,理由是
有人可能想要创建一个具有
{__proto__: null}原型的类
而争论的那一方最终占了上风。
我无法理解这个假设的用例。一方面,虽然这样的类的声明是合法的,但似乎实例化以这种方式声明的类是不合法的。尝试在 Node.js 或 Chrome 中从上面实例化 foo 类会给我一个非常愚蠢的错误
TypeError: function is not a function
虽然在 Firefox 中做同样的事情给了我
TypeError: function () {
} is not a constructor
在类上定义构造函数没有帮助,如 MDN 当前的特性示例所示;如果我尝试实例化这个类:
class bar extends null {
constructor(){}
}
那么 Chrome/Node 告诉我:
ReferenceError: this is not defined
Firefox 告诉我:
ReferenceError: |this| used uninitialized in bar class constructor
这一切的疯狂是什么?为什么这些空扩展类不可实例化?鉴于它们不可实例化,为什么在规范中故意留下创建它们的可能性,以及为什么一些 MDN 作者认为它是noteworthy enough to document?此功能有哪些可能的用例?
【问题讨论】:
-
让
constructor返回Object.create(null)作为替代。这显然可以让您避免自动调用super。 jsfiddle.net/w7y2mbcd 但是我猜它实际上不是那个类的成员。 -
也许让它返回
Object.create(bar.prototype)。 jsfiddle.net/w7y2mbcd/1 -
@squint nice - 您的第二条评论提供了一种实际实例化空扩展类的方法,导致对象不具有
Object.prototype中的任何方法,例如.toString()或.isPrototypeOf()。这比我得到的还远,虽然我仍然不太清楚你为什么想要这样一个对象。 -
我认为有时人们只想要一个干净的物体。这在我们有
Map之前更重要,所以他们会使用Object.create(null)作为通用映射,它可以保存事先不知道的任意属性,这样您就可以保证任何属性查找都来自与交互对象而不是默认继承。现在似乎不那么重要了,但话又说回来,这里和那里可能有一些用例。虽然不知道它们是什么。 -
FWIW,spec 表示
extends后面可以跟任何 LeftHandSideExpression,这基本上意味着可以放在=左侧的任何内容。这包括foo()和null之类的东西。现在,null = 42;和foo() = 42都没有意义,但它们是有效的并且会引发运行时错误。 OTOH,class Foo extends bar() {}有道理。 编辑: 呃,foo() = 42和null = 42似乎是早期错误,几乎就像语法错误:-/
标签: javascript ecmascript-6 es6-class