Saya membuat kelas Javascript dan saya ingin memiliki bidang statis publik seperti di Java. Ini adalah kode yang relevan:
export default class Agent {
CIRCLE: 1,
SQUARE: 2,
...
Ini adalah kesalahan yang saya dapatkan:
line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.
Sepertinya modul ES6 tidak mengizinkan ini. Adakah cara untuk mendapatkan perilaku yang diinginkan atau apakah saya harus menulis yang getter?
javascript
ecmascript-6
class-fields
aebabis
sumber
sumber
Jawaban:
Anda membuat "bidang statis publik" menggunakan pengakses dan kata kunci "statis":
class Agent { static get CIRCLE() { return 1; } static get SQUARE() { return 2; } } Agent.CIRCLE; // 1
Melihat spesifikasi, 14.5 - Definisi Kelas - Anda akan melihat sesuatu yang relevan dan mencurigakan :)
Jadi dari sana Anda dapat mengikuti ke 14.5.14 - Runtime Semantics: ClassDefinitionEvaluation - untuk memeriksa ulang apakah benar-benar berfungsi seperti yang diharapkan. Secara khusus, langkah 20:
IsStatic didefinisikan sebelumnya di 14.5.9
Jadi
PropertyMethodDefinition
disebut dengan "F" (konstruktor, objek fungsi) sebagai argumen, yang pada gilirannya membuat metode pengakses pada objek itu .Ini sudah berfungsi setidaknya di IETP (pratinjau teknis), serta kompiler 6to5 dan Traceur.
sumber
unsafe.enable_getters_and_setters=true
ke .flowconfig Anda di bawah[options]
(yang mengganggu).Ada proposal ECMAScript Tahap 3 yang disebut "Fitur Kelas Statis" oleh Daniel Ehrenberg dan Jeff Morrison yang bertujuan untuk memecahkan masalah ini. Bersama dengan proposal "Bidang Kelas" Tahap 3 , kode masa depan akan terlihat seperti ini:
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' } }
Di atas sama dengan:
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 mendukung transpiling bidang kelas melalui @ babel / plugin-proposal-class-properties (disertakan dalam preset stage-3 ), sehingga Anda dapat menggunakan fitur ini meskipun runtime JavaScript Anda tidak mendukungnya.
Dibandingkan dengan solusi @ kangax untuk mendeklarasikan getter, solusi ini juga bisa lebih berkinerja, karena di sini properti diakses secara langsung daripada melalui pemanggilan fungsi.
Jika proposal ini diterima, maka dimungkinkan untuk menulis kode JavaScript dengan cara yang lebih mirip dengan bahasa berorientasi objek tradisional seperti Java dan C♯.
Edit : Proposal bidang kelas terpadu sekarang berada di tahap 3; perbarui ke paket Babel v7.x.
Sunting (Feb 2020) : Fitur kelas statis telah dibagi menjadi proposal yang berbeda. Terima kasih @ GOTO0!
sumber
Dalam draf ECMAScript 6 saat ini (per Februari 2015), semua properti kelas harus berupa metode, bukan nilai (perhatikan dalam ECMAScript "properti" memiliki konsep yang mirip dengan bidang OOP, kecuali nilai bidang harus berupa
Function
objek, bukan nilai apa pun nilai lain seperti aNumber
atauObject
).Anda masih dapat menentukan ini menggunakan penentu properti konstruktor ECMAScript tradisional:
class Agent { } Agent.CIRCLE = 1; Agent.SQUARE = 2; ...
sumber
class
sintaks ES6 hanyalah gula sintaksis untuk fungsi dan prototipe konstruktor JS tradisional.enum
).class
sintaksis juga memiliki perbedaan nuansa tertentu. Misalnya, metode yang dideklarasikan denganClass.prototype.method = function () {};
dapat dihitung (terlihat dengan loop for-in), sedangkanclass
metode tidak dapat dihitung.Untuk mendapatkan keuntungan penuh dari variabel statis saya mengikuti pendekatan ini. Untuk lebih spesifik, kita bisa menggunakannya untuk menggunakan variabel privat atau hanya memiliki pengambil publik, atau memiliki keduanya pengambil atau penyetel. Dalam kasus terakhir, ini sama dengan salah satu solusi yang diposting di atas.
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'];
Saya dapat membuat kelas lain yang memperluas Url dan berhasil.
Saya menggunakan babel untuk mengubah kode ES6 saya ke ES5
sumber
class Url { static getQueries… }; Url.staticMember = [];
jauh lebih sederhana?===
perbandingan kedua hasilfalse
, btwJawaban @kangax tidak meniru seluruh perilaku statis bahasa OOP tradisional, karena Anda tidak dapat mengakses properti statis dengan contoh seperti itu
const agent = new Agent; agent.CIRCLE; // Undefined
Jika Anda ingin mengakses properti statis seperti OOP, berikut adalah solusi saya:
class NewApp { get MULTIPLE_VERSIONS_SUPPORTED() { return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance } } NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;
Kode tes sebagai berikut.
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
sumber
static
bidang dengan sebuah contoh akan agak tidak biasa, bukan? Dalam beberapa bahasa, seperti Java, IDE sebenarnya mengeluarkan peringatan / petunjuk jika Anda melakukan hal seperti itu.