Как и почему я должен писать класс, который расширяет null?
JavaScript синтаксис класса, добавленный в ES6, по-видимому, делает его законным для extend null
:
class foo extends null {}
Некоторый Googling показывает, что он предложил на ES Обсудить, что такие объявления должны быть сделаны ошибкой; однако другие комментаторы утверждали, что они оставлены законными на том основании, что
кто-то может захотеть создать класс с прототипом {__proto__: null}
и эта сторона аргумента в конечном итоге преобладала.
Я не могу полностью понять этот гипотетический вариант использования. Во-первых, хотя объявление такого класса является законным, кажется, что создание экземпляра класса, объявленного таким образом, не является. Попытка создать экземпляр класса foo
сверху в Node.js или Chrome дает мне чудесную ошибку
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 подумал, что это достаточно примечательно для документирования? Какой возможный вариант использования для этой функции?
Ответы
Ответ 1
Создание экземпляров таких классов предназначено для работы; У Chrome и Firefox есть ошибки. Вот Chrome, здесь Firefox. Он отлично работает в Safari (по крайней мере, на хозяине).
В спецификации раньше было ошибка, из-за которой их невозможно было создать, но она была исправлена некоторое время. (Там все еще связанный, но это не то, что вы видите.)
Пример использования примерно такой же, как у Object.create(null)
. Иногда вам нужно что-то, что не наследуется от Object.prototype
.
Ответ 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.