Я создаю класс Javascript, и я хотел бы иметь общедоступное статическое поле, как в Java. Это соответствующий код:
export default class Agent {
CIRCLE: 1,
SQUARE: 2,
...
Это ошибка, которую я получаю:
line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.
Похоже, модули ES6 не позволяют этого. Есть ли способ добиться желаемого поведения или мне нужно написать геттер?
Ответы:
Вы создаете «общедоступное статическое поле», используя метод доступа и ключевое слово «static»:
class Agent { static get CIRCLE() { return 1; } static get SQUARE() { return 2; } } Agent.CIRCLE; // 1
Взглянув на спецификацию 14.5 - Определения классов, вы увидите что-то подозрительно уместное :)
Итак, оттуда вы можете перейти к 14.5.14 - Семантика времени выполнения: ClassDefinitionEvaluation - чтобы дважды проверить, действительно ли он делает то, что кажется. В частности, шаг 20:
IsStatic определен ранее в 14.5.9.
Так
PropertyMethodDefinition
вызывается с "F" (конструктор, функциональный объект) в качестве аргумента, который, в свою очередь, создает метод доступа к этому объекту. .Это уже работает по крайней мере в IETP (техническая превью), а также в компиляторах 6to5 и Traceur.
источник
unsafe.enable_getters_and_setters=true
в свой .flowconfig под[options]
(что раздражает).Даниэль Эренберг и Джефф Моррисон разработали 3-й этап предложения ECMAScript под названием «Функции статического класса» , который направлен на решение этой проблемы. Вместе с предложением этапа 3 «Поля классов» будущий код будет выглядеть следующим образом:
class MyClass { static myStaticProp = 42; myProp = 42; myProp2 = this.myProp; myBoundFunc = () => { console.log(this.myProp); }; constructor() { console.log(MyClass.myStaticProp); // Prints '42' console.log(this.myProp); // Prints '42' this.myBoundFunc(); // Prints '42' } }
Вышеуказанное эквивалентно:
class MyClass { constructor() { this.myProp = 42; this.myProp2 = this.myProp; this.myBoundFunc = () => { console.log(this.myProp); }; console.log(MyClass.myStaticProp); // Prints '42' console.log(this.myProp); // Prints '42' this.myBoundFunc(); // Prints '42' } } MyClass.myStaticProp = 42;
Babel поддерживает перенос полей класса через свойства @ babel / plugin- scheme -class (включен в предустановку stage-3 ), так что вы можете использовать эту функцию, даже если ваша среда выполнения JavaScript не поддерживает ее.
По сравнению с решением @kangax по объявлению геттера это решение также может быть более производительным, поскольку здесь доступ к свойству осуществляется напрямую, а не через вызов функции.
Если это предложение будет принято, появится возможность писать код JavaScript способом, более похожим на традиционные объектно-ориентированные языки, такие как Java и C♯.
Изменить : предложение унифицированных полей класса сейчас находится на этапе 3; обновление до пакетов Babel v7.x.
Изменить (февраль 2020 г.) : функции статического класса были разделены на другое предложение. Спасибо @ GOTO0!
источник
В текущих черновиках ECMAScript 6 (по состоянию на февраль 2015 г.) все свойства класса должны быть методами, а не значениями (обратите внимание, что в ECMAScript «свойство» аналогично концепции поля ООП, за исключением того, что значение поля должно быть
Function
объектом, а не каким-либо другое значение, такое какNumber
илиObject
).Вы по-прежнему можете указать их, используя традиционные спецификаторы свойств конструктора ECMAScript:
class Agent { } Agent.CIRCLE = 1; Agent.SQUARE = 2; ...
источник
class
синтаксис ES6 - это просто синтаксический сахар для традиционных функций конструктора JS и прототипов.enum
).class
синтаксис также имеет определенные нюансы. Например, метод, объявленный с помощью,Class.prototype.method = function () {};
является перечислимым (видимым с помощью циклов for-in), в то время какclass
методы не перечисляются.Чтобы получить все преимущества статической переменной, я использовал этот подход. Чтобы быть более конкретным, мы можем использовать его для использования частной переменной или наличия только общедоступного получателя или наличия обоих получателей или установщиков. В последнем случае это то же самое, что и одно из решений, опубликованных выше.
var Url = (() => { let _staticMember = []; return class { static getQueries(hash = document.location.hash) { return hash; } static get staticMember(){ return _staticMember; } }; })(); Usages: console.log(Url.staticMember); // []; Url.staticMember.push('it works'); console.log(Url.staticMember); // ['it works'];
Я мог создать еще один класс, расширяющий URL, и это сработало.
Я использовал babel для преобразования моего кода ES6 в ES5
источник
class Url { static getQueries… }; Url.staticMember = [];
было бы ничего проще?===
Оба эти сравнения дают результатыfalse
, кстати,Ответ @kangax не имитирует все статическое поведение традиционного языка ООП, потому что вы не можете получить доступ к статическому свойству с его экземпляром, например
const agent = new Agent; agent.CIRCLE; // Undefined
Если вы хотите получить доступ к статическому свойству так же, как ООП, вот мое решение:
class NewApp { get MULTIPLE_VERSIONS_SUPPORTED() { return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance } } NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;
Проверьте код следующим образом.
class NewApp { get MULTIPLE_VERSIONS_SUPPORTED() { console.log('this.constructor.name:', this.constructor.name); // late binding return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; } } // Static property can be accessed by class NewApp.MULTIPLE_VERSIONS_SUPPORTED = true; const newApp = new NewApp; // Static property can be accessed by it's instances console.log('newApp.MULTIPLE_VERSIONS_SUPPORTED:', newApp.MULTIPLE_VERSIONS_SUPPORTED); // true // Inheritance class StandardApp extends NewApp {} // Static property can be inherited console.log('StandardApp.MULTIPLE_VERSIONS_SUPPORTED:', StandardApp.MULTIPLE_VERSIONS_SUPPORTED); // true // Static property can be overwritten StandardApp.MULTIPLE_VERSIONS_SUPPORTED = false; const std = new StandardApp; console.log('std.MULTIPLE_VERSIONS_SUPPORTED:', std.MULTIPLE_VERSIONS_SUPPORTED); // false
источник
static
полю с помощью экземпляра был бы довольно необычным, не так ли? На некоторых языках, таких как Java, IDE фактически выдает предупреждение / подсказку, если вы делаете что-то подобное.