Получить доступ к статическим свойствам класса с помощью BabelJS 6
Ниже приведено минимальное приложение, демонстрирующее проблему:
'use strict';
var _ = require('underscore');
class Model
{
constructor(value) {
this._value = value;
}
get value() {
return this._value;
}
toJS() {
return this.value;
}
}
class ObjectModel extends Model
{
static properties = {};
constructor(value) {
super(_.extend({}, new.target.properties, _.pick(value, _.keys(new.target.properties))));
}
}
class PostModel extends ObjectModel
{
static properties = {
title: 'Hello'
/* content: '<p>Lorem ipsum dolor sit amet</p>' */
};
}
console.log(new PostModel({title: 'Nice day', aa: 11, bb: 22}).toJS());
Должно производить {title: 'Nice day'}
, Вместо этого он даже не компилируется. Я получаю это:
$ babel app.js
SyntaxError: app.js: 'this' is not allowed before super()
Я понимаю, почему это было сделано для свойств объекта. Но я не могу понять, почему это также было сделано для переменных класса.
В BabelJS 5 я использовал этот трюк, который сделал эту работу:
class ObjectModel extends Model
{
static properties = {};
constructor(value) {
if (0) { super(); }
super(_.extend({}, this.constructor.properties, _.pick(value, _.keys(this.constructor.properties))));
}
}
В версии 6 он компилируется, но при запуске выдает ошибку:
Uncaught TypeError: Cannot read property 'constructor' of undefined
Есть ли способ получить доступ к классу статических переменных перед вызовом super
? Используя что-то вроде init()
вместо constructor
это не вариант. Может быть, создать собственный плагин преобразования?
Детали системы:
$ babel --version
6.2.0 (babel-core 6.2.1)
$ cat .babelrc
{
"presets": ["es2015", "stage-1"]
}
$ babel-doctor
Babel Doctor
Running sanity checks on your system. This may take a few minutes...
✔ Found config at /path/to/.babelrc
✔ No duplicate babel packages found
✔ All babel packages appear to be up to date
✔ You're on npm >=3.3.0
Everything looks all right!
1 ответ
Решение было следующим:
Придерживайтесь
new.target
как предложено @sjrd и @loganfsmyth:class ObjectModel extends Model { static properties = {}; constructor(value) { super(_.extend({}, new.target.properties, _.pick(value, _.keys(new.target.properties)))); } }
Создать транспортер, который преобразует все
new.target
(ES6) вthis.constructor
(ES5):function transpileNewTarget() { return { visitor: { MetaProperty(path) { if (path.isMetaProperty() && path.node.meta.name == 'new' && path.node.property.name == 'target') { path.replaceWithSourceString('this.constructor'); } } } }; }