91

Javascript クラスを作成していますが、Java のような public static フィールドが必要です。これは関連するコードです:

export default class Agent {
    CIRCLE: 1,
    SQUARE: 2,
    ...

これは私が得るエラーです:

line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.

ES6 モジュールではこれが許可されていないようです。目的の動作を取得する方法はありますか、またはゲッターを作成する必要がありますか?

4

5 に答える 5

59

ECMAScript 2022 以降、Java や C# などの従来のクラス指向言語と同様に、次のようなことができます。

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;

この機能は、Daniel Ehrenberg らによる「静的クラス機能」および「クラス フィールド」の提案に追加されました。Google Chrome (および新しい Edge) は、 Node.js 12+と同等のバージョン 72で両方の提案のサポートを開始しました。Firefox は、バージョン 69以降のパブリック インスタンス フィールドとバージョン 75以降の静的インスタンス フィールドをサポートしています。Safari は、バージョン 14.1以降、両方をサポートしています。詳しくはcaniuse.comをご覧ください。

これらの機能をまだサポートしていない古いブラウザーの場合、Babelを使用してクラス フィールドをトランスパイルできます。これには、@babel/plugin-proposal-class-propertiesを有効にする必要があります ( v7.14.0 以降の @babel/plugin-env ではデフォルトで有効になっています)。


ゲッターを宣言する @kangax のソリューションと比較すると、このソリューションは、関数を呼び出す代わりにプロパティに直接アクセスするため、よりパフォーマンスが高くなる可能性があります。


編集: 統一されたクラス フィールドの提案は、現在ステージ 3 にあります。

編集 (2020 年 2 月) : 静的クラス機能は別の提案に分割されました。ありがとう@GOTO0!

編集 (2021 年 3 月) : Safari を除いて、2020 年 4 月以降にリリースされたすべての主要なブラウザーがこの機能をサポートするようになりました!

編集 (2021 年 6 月) : 両方の提案がECMAScript 言語委員会であるTC39によって受け入れられ、Safari はバージョン 14.1 でこの機能を出荷しました!

于 2016-08-02T18:18:07.673 に答える
29

ECMAScript 6 の現在のドラフト (2015 年 2 月現在) では、すべてのクラス プロパティは値ではなくメソッドである必要があります (ECMAScript では、「プロパティ」の概念は OOP フィールドと似ていますが、フィールド値は任意のオブジェクトではなく、Functionオブジェクトでなければなりません。 aNumberまたはなどの他の値Object)。

従来の ECMAScript コンストラクタ プロパティ指定子を使用してこれらを指定することもできます。

 class Agent {
 }
 Agent.CIRCLE = 1;
 Agent.SQUARE = 2;
 ...
于 2015-02-11T02:53:09.193 に答える
4

静的変数を最大限に活用するために、私はこのアプローチに従いました。具体的には、プライベート変数を使用したり、パブリックゲッターのみを使用したり、ゲッターとセッターの両方を使用したりするために使用できます。最後のケースでは、上記のソリューションの 1 つと同じです。

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 に変換しました

于 2015-07-06T00:05:23.410 に答える
-1

@kangax の答えは、従来の OOP 言語の静的な動作全体を模倣していません。これは、インスタンスのような静的プロパティにアクセスできないためです。const agent = new Agent; agent.CIRCLE; // Undefined

OOPと同じように静的プロパティにアクセスしたい場合、私の解決策は次のとおりです。

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

于 2017-03-17T09:04:33.170 に答える