Как я могу записать аналог class MyClass extends EventTarget{}
, без использования синтаксиса "class"? В спецификации сказано что это только синтаксический сахар, что происходит при его использовании?
Мне интересно узнать что именно происходит при произнесении этого заклинания. Я пробовал что-то вроде
function MyClass(){
var tmp = new EventTarget;
//здесь можно задать новые методы, например tmp.hi = _=>{alert("Hi")}
return tmp;
}
Но в этом случае (new MyClass).constructor.name
выводит "EventTarget".
Это не удобно для отладки.
В общем случае конструкция
class MyTarget extends EventTarget {
constructor() {
super();
// init MyTarget
}
foo() {
// ...
}
}
(почти) эквивалентна следующей:
function MyTarget() {
EventTarget.apply(this);
// init MyTarget
}
MyTarget.prototype = Object.create(EventTarget.prototype);
MyTarget.prototype.constructor = MyTarget;
MyTarget.prototype.foo = function() {
// ...
};
Однако так сделать невозможно, т. к. EventTarget
не допускает вызов через apply
, только через new
— так что в данном случае можно только использовать extends
.
Если хочется узнать подробнее, нужно читать про цепочку прототипов и свойство Function.prototype
в JS: например, MDN или ООП в прототипном стиле.
UPD
Более точный вариант, использующий рефлексию и изменения прототипа (не рекомендуется к production-использованию!):
function MyTarget() {
const self = Reflect.construct(EventTarget, arguments, this.constructor);
// init self
return self;
}
Object.setPrototypeOf(MyTarget, EventTarget);
MyTarget.prototype = Object.create(EventTarget.prototype);
MyTarget.prototype.constructor = MyTarget;
MyTarget.prototype.foo = function() {
// ...
};
UPD2
Вариант для старых браузеров, конкретно для IE, не поддерживающего Reflect.construct
(также исключительно в демонстрационных целях):
function MyTarget() {
var bound = EventTarget.bind(null, arguments);
var self = new bound();
Object.setPrototypeOf(self, MyTarget.prototype);
// init self
return self;
}
Object.setPrototypeOf(MyTarget, EventTarget);
MyTarget.prototype = Object.create(EventTarget.prototype);
MyTarget.prototype.constructor = MyTarget;
MyTarget.prototype.foo = function() {
// ...
};
Также для поддержки IE10- можно заменить Object.setPrototypeOf(o, proto);
, на o.__proto__ = proto;
.
Однако насколько я могу судить, всё это довольно бессмысленно. Reflect.construct
поддерживается всеми браузерами кроме IE, а IE, если верить MDN не поддерживает конструктор EventTarget
. ¯_(ツ)_/¯
UPD3
Исправил ошибку в примере с Reflect.construct
— нужно было возвращать именно объект от Reflect.construct
, а возвращался (неявно) объект, созданный new
.
Дополнительно также отмечу, что для ещё большего соответствия поведению extends
стоит вместо
MyTarget.prototype = Object.create(EventTarget.prototype);
MyTarget.prototype.constructor = MyTarget;
делать так (чтобы свойство constructor
было неперечисляемым):
MyTarget.prototype = Object.create(EventTarget.prototype, {
constructor: { value: MyTarget, writable: true, configurable: true }
});
Вы правильно понимаете, что это синтаксический сахар, но он призван упростить чтение кода.
На самом деле происходит прототипное наследование
function EventTarget(eventName) {
this.eventName = eventName;
}
EventTarget.prototype.eventFunc = function() {
console.log(this.eventName);
};
function MyClass(eventName) {
EventTarget.call(this, eventName);
}
MyClass.prototype = new EventTarget(null);
MyClass.prototype.anotherFunc = function() {
this.eventFunc();
};
var m = new MyClass('It is event');
m.anotherFunc();
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Пожалуйста, подскажите, как можно при: добавлении, удаление классов (при toggleClass например) сохранять результат после перезагрузки страницыЯ...
Есть массив,числа это типа номера маршруток на данном улицеЧисла идут только на возрастание и по порядку
В чём ошибка моего кода? Первая ветвь работает нормально, как сделать чтобы при повторном нажатии заработала и вторая ветвь?