我如何以及为啥要编写一个扩展 null 的类?
Posted
技术标签:
【中文标题】我如何以及为啥要编写一个扩展 null 的类?【英文标题】:How and why would I write a class that extends null?我如何以及为什么要编写一个扩展 null 的类? 【发布时间】: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
似乎是早期错误,几乎就像语法错误:-/
【参考方案1】:
EDIT(2021 年):TC39,它指定 JavaScript 仍未完全解决它应该如何工作。这需要在浏览器能够始终如一地实现它之前发生。您可以关注here的最新努力。
原答案:
实例化这样的类是为了工作; Chrome 和 Firefox 只是有错误。 Here's Chrome 的,here's Firefox 的。它在 Safari 中运行良好(至少在 master 上)。
规范中曾经有一个bug,这使得它们无法实例化,但它已经修复了一段时间。 (有一个相关的 still,但这不是你看到的。)
用例与Object.create(null)
的用例大致相同。有时你想要一些不继承自 Object.prototype
的东西。
【讨论】:
假设我想连接每个对象原型,但我用extend null
或Object.create(null)
创建的对象原型?
看起来关于extends null
的规范有changed 和Chrome isn't fixing this bug because of it。【参考方案2】:
回答第二部分:
我无法理解这个假设的用例。
这样,您的对象的原型链中就不会有Object.prototype
。
class Hash extends null
var o = ;
var hash = new Hash;
o["foo"] = 5;
hash["foo"] = 5;
// both are used as hash maps (or use `Map`).
hash["toString"]; // undefined
o["toString"]; // function
正如我们所知,undefined
实际上不是一个函数。在这种情况下,我们可以创建对象而不必担心对不应该存在的字段的调用。
这是Object.create(null)
的常见模式,在很多代码库中都很常见,包括像 NodeJS 这样的大型代码库。
【讨论】:
以上是关于我如何以及为啥要编写一个扩展 null 的类?的主要内容,如果未能解决你的问题,请参考以下文章
我无法理解错误是啥以及为啥 e.currentTarget.value 为 null