JavaScript 的 class 语法,显然使得 extend
null
变得合法:
class foo extends null {}
new foo();
一些谷歌搜索显示,在 ES Discuss 上建议这样的声明是错误的;然而,其他评论者认为它们应该保持合法,因为
有人可能想创建一个具有
原型的类{__proto__: null}
这一方的论点最终占了上风。
我无法理解这个假设的用例。一方面,虽然这样一个类的“声明”是合法的,但以这种方式声明的“实例化”类似乎是不合法的。尝试在 Node.js 或 Chrome 中实例化上面的类 foo
给了我一个非常愚蠢的错误
类型错误:函数不是函数
在 Firefox 中做同样的事情给了我类型错误:函数(){
} 不是构造函数
在类上定义构造函数没有帮助,如 MDN 当前的功能示例所示;如果我尝试实例化这个类:
class bar extends null {
constructor() {}
}
new bar();
ReferenceError:未定义
Firefox 告诉我:参考错误:|这个|在 bar 类构造函数中使用未初始化
这一切到底是怎么回事?为什么这些空扩展类不可实例化?鉴于它们不可实例化,为什么在规范中故意留下了创建它们的可能性,以及为什么一些 MDN 作者认为它“值得记录”?此功能有哪些可能的用例?
编辑(2021):TC39,它指定了 JavaScript 仍然没有准确地解决它应该如何工作。这需要在浏览器能够一致地实现它之前发生。您可以关注
这里原答案:
实例化这样的类是为了工作; Chrome 和 Firefox 只是存在错误。Chrome,这里 Firefox。它在 Safari 中运行良好(至少在 master 上)。
规范中曾经有一个bug,导致它们无法实例化,但它已经修复了一段时间。 (还有一个相关的,但那不是你看到的。) 用例与
Object.create(null)
大致相同。有时您想要的东西不是从 Object.prototype
继承的。
回答
第二部分:
我无法理解这个假设的用例。
这样,你的对象的原型链中就不会有 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 的类,这样
class bar extends null{
constructor(){
super() //required
}
}
//super is not a function
//change the super class (for static methods only)
Object.setPrototypeOf(bar, class{})
let instance = new bar()
//instances still have null prototype
console.log(instance.toString) //undefined