Я пытаюсь эмулировать этот JavaScript без использования ключевых слов ES6 (например, без class
, super
или extends
):
class Foo {
constructor() {
if (!new.target)
console.log('Foo() must be called with new');
}
}
class Bar extends Foo {
constructor() {
super(...arguments);
}
}
var bar = new Bar();
var barIsFoo = bar instanceof Foo;
console.log(barIsFoo); // true
Я получил это далеко, но они не эквивалентны.Следующие броски (я регистрирую вместо), в то время как последний не делает:
function Foo() {
if (!new.target)
console.log('Foo() must be called with new');
}
function Bar() {
Foo.apply(this, arguments)
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.constructor = Bar;
var bar = new Bar();
var barIsFoo = bar instanceof Foo;
console.log(barIsFoo);
Итак, как мне эмулировать предоставление значения для new.target
, когда я звоню в Foo
из Bar
?
ТакПохоже, что нет apply
или call
, который позволяет передавать new.target
.Я полагаю, что это победило бы цель new.target
(хотя тот факт, что все в JS является публичным, мне очень понравился).
Так что для эмуляции в ES5 нам нужно что-то добавить.
Одно решение в ответе ниже выделяет новый объект.
В этом решении добавлены новые функции construct
, которые можно как обычно объединить в ES5, и оставить саму функцию свободной, чтобы ничего не делать, кроме проверки, используется ли она в качестве конструктора.
function Foo() {
if (!new.target)
throw 'Foo() must be called with new';
console.log('Foo new check');
Foo.prototype.construct.apply(this, arguments);
}
Foo.prototype.construct = function() {
console.log('Foo construction logic');
}
function Bar() {
if (!new.target)
throw 'Bar() must be called with new';
console.log('Bar new check');
Bar.prototype.construct.apply(this, arguments);
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.constructor = Bar;
Bar.prototype.construct = function() {
// super()
Foo.prototype.construct.apply(this, arguments);
console.log('Bar construction logic');
}
var bar = new Bar();
var barIsFoo = bar instanceof Foo;
console.log(barIsFoo);
В итоге, кажется, что ES6 обладает не не просто синтаксическим сахаром по сравнению с ES5.Конечно, они могли бы просто добавить Function.prototype.super(target, arguments, newTarget)
, и тогда мы могли бы просто использовать это.Надеюсь, они это сделают!
Только super
может вызвать функцию в Javascript, и this
не будет доступен немедленно.Так что super
уникален.И super
может быть вызван только в контексте constructor
, который может использоваться только в контексте class
.Ооо, все эти ключевые слова необходимы, чтобы super
работал.Итак, Javascript представил очень специфическую объектно-ориентированную функцию.Похоже, что построение языка поверх идеи «прототипа» имеет свои ограничения.
Какой позор ...
Интересно, почему вдруг javascript решил применить этот один инвариант.this
недоступен до вызова super
.Почему бы просто не сделать super
короткой рукой для BaseType.prototype.constructor.call(this, ...)
.Почему бы не позволить его вызывать более одного раза?В Javascript мы можем отбросить многие другие проблемы, зачем начинать применять их сейчас?
Ну, в любом случае ...
Итак, двойная нижняя строка, существует ранний связанный вызов Javascriptsuper
, у которого нет эквивалента с поздней привязкой (в отличие, например, от foo.bar()
, который можно назвать с поздней (r) связью через bar.call('foo')
).