синтаксис классов JavaScript, добавленный в ES6, по-видимому, делает допустимым расширить null
:
class foo extends null {}
Некоторые гуглы показывают, что на ES Discuss было предложено считать такие заявления ошибкой; однако другие комментаторы утверждали, что их следует оставить законными на том основании, что
кто-то может захотеть создать класс с прототипом
{__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 считает, что это достаточно примечательный, чтобы задокументировать? Какой возможный вариант использования этой функции?
constructor
вернетObject.create(null)
в качестве замены. Очевидно, это позволяет избежать автоматического вызоваsuper
. jsfiddle.net/w7y2mbcd Но тогда я думаю, что на самом деле это не член этого класса. - person   schedule 16.12.2016Object.create(bar.prototype)
. jsfiddle.net/w7y2mbcd/1 - person   schedule 16.12.2016Object.prototype
, таких как.toString()
или.isPrototypeOf()
. Это больше, чем я понял, хотя я все еще не совсем уверен, зачем вам нужен такой объект. - person Mark Amery   schedule 16.12.2016Map
, поэтому они использовалиObject.create(null)
в качестве универсальной карты, которая может содержать произвольные свойства, неизвестные заранее, чтобы можно было гарантировать, что поиск любого свойства происходит в результате взаимодействия с объектом, а не наследование по умолчанию. Сейчас это кажется менее важным, но опять же, вероятно, здесь и там есть несколько вариантов использования. Хотя не знаю, что они из себя представляют. - person   schedule 16.12.2016super
, если нет родительского конструктора. Но тогда я действительно не думал об этом. - person   schedule 16.12.2016super
в этой ветке комментариев, но не объясняли его подробно (возможно, предполагая, что ваша аудитория знает больше о классах ES6, чем я лично). Является ли этот неявный вызов причиной ошибок при попытке создать экземплярbar
из моего вопроса? При каких обстоятельствах происходит этот неявный вызов и почему? - person Mark Amery   schedule 16.12.2016class
, родительский конструктор автоматически вызывается для объекта или что, если вы пытаетесь сослаться наthis
, вы должны сначала вручную вызватьsuper()
... но я могу некоторые детали перепутаны, поэтому вам лучше поискать другие ресурсы для лучшего объяснения. Но да, я думаю, что это, вероятно, причина ошибок, хотя я могу сильно ошибаться в этом. - person   schedule 16.12.2016extends
может быть за которым следует любое LeftHandSideExpression, что в основном означает все, что можно поставить слева от=
. Это включает в себя такие вещи, какfoo()
иnull
. Теперь ниnull = 42;
, ниfoo() = 42
не имеют смысла, но они допустимы и вызовут ошибку времени выполнения. OTOH,class Foo extends bar() {}
имеет смысл. edit: Э-э,foo() = 42
иnull = 42
кажутся ранними ошибками, которые почти как синтаксические ошибки :-/ - person Felix Kling   schedule 16.12.2016