Alternatywne zmienne klasy ES6

491

Obecnie w ES5 wielu z nas używa następującego wzorca w ramach do tworzenia klas i zmiennych klas, co jest wygodne:

// ES 5
FrameWork.Class({

    variable: 'string',
    variable2: true,

    init: function(){

    },

    addItem: function(){

    }

});

W ES6 możesz tworzyć klasy natywnie, ale nie ma opcji, aby mieć zmienne klas:

// ES6
class MyClass {
    const MY_CONST = 'string'; // <-- this is not possible in ES6
    constructor(){
        this.MY_CONST;
    }
}

Niestety powyższe nie zadziała, ponieważ klasy mogą zawierać tylko metody.

Rozumiem, że mogę this.myVar = truesię constructor... ale ja nie chcę „śmieci” mój konstruktor, zwłaszcza gdy mam 20-30 + params dla większej klasy.

Myślałem o wielu sposobach rozwiązania tego problemu, ale nie znalazłem jeszcze żadnych dobrych. (Na przykład: utwórz ClassConfigmoduł obsługi i przekaż parameterobiekt, który jest zadeklarowany oddzielnie od klasy. Następnie moduł obsługi dołączy do klasy. Myślałem WeakMapsteż o integracji).

Jakie pomysły musiałbyś poradzić sobie w tej sytuacji?

Wintercounter
źródło
1
Twoim głównym problemem jest to, że będziesz mieć powtórzenie this.member = memberu konstruktora z 20-30 parametrami?
Θεόφιλος Μουρατίδης
1
Nie możesz po prostu używać public variable2 = truew klasie? To by to zdefiniowało na prototypie.
14
@ Θεόφιλος Μουρατίδης: Tak, a także chcę użyć mojego konstruktora do procedur inicjalizacji, a nie do deklaracji zmiennych.
wintercounter
@derylius: To jest główny problem, nie ma takiej funkcji. Nawet wykorzystanie publiczne / prywatne nie jest jeszcze określone w projekcie ES6. Wypróbuj go: es6fiddle.net
wintercounter
Zgodnie z najnowszymi, ma tę funkcję: wiki.ecmascript.org/doku.php?id=harmony:classes

Odpowiedzi:

514

Aktualizacja 2018:

Jest teraz propozycja etapu 3 - nie mogę się doczekać, aby ta odpowiedź stała się nieaktualna za kilka miesięcy.

W międzyczasie każdy, kto używa TypeScript lub babel, może użyć składni:

varName = value

Wewnątrz deklaracji klasy / treści wyrażenia zdefiniuje zmienną. Mam nadzieję, że za kilka miesięcy / tygodni będę mógł opublikować aktualizację.

Aktualizacja: Chrome 74 jest teraz dostarczany z działającą składnią.


Notatki na stronie wiki ES dotyczące propozycji w ES6 ( maksymalnie minimalne klasy ) Uwaga:

Nie ma (celowo) bezpośredniego deklaratywnego sposobu zdefiniowania właściwości prototypowych właściwości danych (innych niż metody) ani właściwości instancji

Właściwości klasy i właściwości danych prototypowych należy utworzyć poza deklaracją.

Do właściwości określonych w definicji klasy przypisane są te same atrybuty, jak w przypadku literału obiektu.

Oznacza to, że to , o co prosiłeś, zostało wzięte pod uwagę i zostało wyraźnie odrzucone.

ale dlaczego?

Dobre pytanie. Dobrzy ludzie z TC39 chcą, aby deklaracje klas deklarowały i definiowały możliwości klasy. Nie jego członkowie. Deklaracja klasy ES6 określa umowę dla użytkownika.

Pamiętaj, definicja klasy definiuje metody prototypowe - definiowanie zmiennych w prototypie na ogół nie jest czymś, co robisz. Możesz oczywiście użyć:

constructor(){
    this.foo = bar
}

W konstruktorze, jak sugerowałeś. Zobacz także podsumowanie konsensusu .

ES7 i nowsze

Trwają prace nad nową propozycją dla ES7, która umożliwia bardziej zwięzłe zmienne instancji poprzez deklaracje klas i wyrażenia - https://esdiscuss.org/topic/es7-property-initializers

Benjamin Gruenbaum
źródło
4
@wintercounter ważną rzeczą, którą należy z tego wziąć, jest to, że zezwolenie na zdefiniowanie właściwości zdefiniowałoby je na prototypie, podobnie jak metody, a nie na każdej instancji. Maksymalnie minimalne klasy wciąż znajdują się w swoim podstawowym dziedzictwie prototypowym. To, co naprawdę chcesz zrobić w swoim przypadku, to struktura udostępniania i przypisywanie członków do każdej instancji. Po prostu nie jest to celem klas w ES6 - funkcjonalność udostępniania. Tak więc, aby udostępnić strukturę, musisz trzymać się starej składni. Przynajmniej do ES7 :)
Benjamin Gruenbaum
5
Warto wspomnieć o staticnieruchomościach
Bergi
8
Ups, pierd mózgu. Zapomniałem, że to staticdziała tylko dla metod.
Bergi
637
Może dobrzy ludzie z TC39 powinni nazwać tę koncepcję czymś innym niż „klasa”, jeśli nie chcą, aby zachowywała się tak, jak reszta świata programowania oczekuje od czegoś zwanego „klasą”.
Alex
7
Zobacz także propozycję „Pola klas i właściwości statyczne” (już zaimplementowaną w Babel : github.com/jeffmo/es-class-fields-and-static-properties
Matt Browne
127

Wystarczy dodać do odpowiedzi Benjamina - zmienne klasy są możliwe, ale nie prototypeużyłbyś ich do ustawienia.

Dla zmiennej prawdziwej klasy chciałbyś zrobić coś takiego:

class MyClass {}
MyClass.foo = 'bar';

Z metody klasy można uzyskać dostęp do tej zmiennej jako this.constructor.foo(lub MyClass.foo).

Te właściwości klasy zwykle nie byłyby dostępne z poziomu instancji klasy. tzn. MyClass.foodaje, 'bar'ale new MyClass().foojestundefined

Jeśli chcesz mieć również dostęp do zmiennej klasy z instancji, musisz dodatkowo zdefiniować moduł pobierający:

class MyClass {
    get foo() {
        return this.constructor.foo;
    }
}

MyClass.foo = 'bar';

Testowałem to tylko z Traceur, ale wierzę, że będzie działać tak samo w standardowej implementacji.

JavaScript tak naprawdę nie ma klas . Nawet w ES6 patrzymy na język oparty na obiektach lub prototypach, a nie język oparty na klasach. W dowolny function X () {}, X.prototype.constructorwskazuje z powrotem X. Gdy newoperator jest włączony X, tworzony jest nowy obiekt dziedziczący X.prototype. Wszystkie niezdefiniowane właściwości w tym nowym obiekcie (w tym constructor) są wyszukiwane stamtąd. Możemy myśleć o tym jak o generowaniu właściwości obiektu i klasy.

lizanie
źródło
29

Babel obsługuje zmienne klas w ESNext, sprawdź ten przykład :

class Foo {
  bar = 2
  static iha = 'string'
}

const foo = new Foo();
console.log(foo.bar, foo.iha, Foo.bar, Foo.iha);
// 2, undefined, undefined, 'string'
Kosmetika
źródło
1
Można dokonać bar jest prywatną zmienną klasy udając ją „#” tak: #bar = 2;
Lonnie Best,
26

W twoim przykładzie:

class MyClass {
    const MY_CONST = 'string';
    constructor(){
        this.MY_CONST;
    }
}

Ponieważ MY_CONST jest prymitywny https://developer.mozilla.org/en-US/docs/Glossary/Primitive możemy po prostu zrobić:

class MyClass {
    static get MY_CONST() {
        return 'string';
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass

// alert: string ; true

Ale jeśli MY_CONSTjest typem odniesienia, na przykład static get MY_CONST() {return ['string'];}wyjściem alertu jest ciąg, fałsz . W takim przypadku deleteoperator może wykonać lewę:

class MyClass {
    static get MY_CONST() {
        delete MyClass.MY_CONST;
        return MyClass.MY_CONST = 'string';
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass

// alert: string ; true

I wreszcie dla zmiennej klasy nie const:

class MyClass {
    static get MY_CONST() {
        delete MyClass.MY_CONST;
        return MyClass.MY_CONST = 'string';
    }
    static set U_YIN_YANG(value) {
      delete MyClass.MY_CONST;
      MyClass.MY_CONST = value;
    }
    get MY_CONST() {
        return this.constructor.MY_CONST;
    }
    set MY_CONST(value) {
        this.constructor.MY_CONST = value;
    }
    constructor() {
        alert(this.MY_CONST === this.constructor.MY_CONST);
    }
}
alert(MyClass.MY_CONST);
new MyClass
// alert: string, true
MyClass.MY_CONST = ['string, 42']
alert(MyClass.MY_CONST);
new MyClass
// alert: string, 42 ; true
Oleg Mazko
źródło
5
Unikaj deleteoperatora, jeśli jest sam ze względów wydajnościowych. To, czego tak naprawdę chcesz tutaj Object.defineProperty.
Bergi,
@shinzou Myślałem o tym samym. Jednak niekoniecznie wina OP; to naprawdę język, w którym brakuje odpowiednich mechanizmów do reprezentowania danych w sposób odzwierciedlający ich relacje w świecie rzeczywistym.
user1974458,
17

Ponieważ twój problem ma głównie charakter stylistyczny (nie chcesz wypełniać konstruktora wiązką deklaracji), możesz go rozwiązać również stylistycznie.

Z mojego punktu widzenia w wielu językach opartych na klasach konstruktor może być funkcją nazwaną po samej nazwie klasy. Stylistycznie możemy to wykorzystać, aby stworzyć klasę ES6, która stylistycznie ma sens, ale nie grupuje typowych działań zachodzących w konstruktorze ze wszystkimi deklaracjami własności, które wykonujemy. Po prostu używamy rzeczywistego konstruktora JS jako „obszaru deklaracji”, a następnie tworzymy klasę o nazwie funkcja, którą inaczej traktujemy jako obszar „innych rzeczy konstruktora”, nazywając ją na końcu prawdziwego konstruktora.

„użyj ścisłego”;

klasa MyClass
{
    // zadeklaruj tylko swoje właściwości, a następnie wywołaj this.ClassName (); stąd
    konstruktor(){
        this.prop1 = „bla 1”;
        this.prop2 = 'bla 2';
        this.prop3 = 'bla 3';
        this.MyClass ();
    }

    // wszelkiego rodzaju inne rzeczy „konstruktorskie”, już nie pomieszane z deklaracjami
    Moja klasa() {
        rób cokolwiek();
    }
}

Oba zostaną wywołane w trakcie tworzenia nowej instancji.

Trochę tak, jakbyś miał 2 konstruktory, w których oddzielasz deklaracje i inne działania konstruktora, które chcesz podjąć, i stylistycznie sprawia, że ​​nie jest zbyt trudno zrozumieć, że to się dzieje.

Uważam, że jest to dobry styl do użycia w przypadku wielu deklaracji i / lub wielu działań, które muszą się zdarzyć przy tworzeniu instancji i chcą oddzielić te dwie idee od siebie.


UWAGA : Bardzo celowo nie używam typowych idiomatycznych pomysłów „inicjalizacji” (jak metoda init()lub initialize()), ponieważ są one często używane inaczej. Istnieje pewna domniemana różnica między ideą konstruowania i inicjowania. Pracując z konstruktorami ludzie wiedzą, że są wywoływani automatycznie w ramach tworzenia instancji. Widząc initmetodę, którą wiele osób zakłada bez drugiego spojrzenia, że ​​muszą robić coś podobnego var mc = MyClass(); mc.init();, ponieważ zazwyczaj tak się inicjuje. Nie próbuję dodawać procesu inicjalizacji dla użytkownika klasy, próbuję dodać do procesu budowy samej klasy.

Chociaż niektórzy ludzie mogą przez chwilę zrobić podwójne ujęcie, to w rzeczywistości o to chodzi: komunikuje im, że zamiar jest częścią konstrukcji, nawet jeśli sprawia to, że robią trochę podwójnego ujęcia i iść ”to nie jest jak działają konstruktory ES6 ”i poświęć chwilę, by spojrzeć na rzeczywistego konstruktora, aby powiedzieć„ och, nazywają to na dole, rozumiem ”, to o wiele lepsze niż NIE komunikowanie tego zamiaru (lub niepoprawne komunikowanie go) i prawdopodobnie uzyskanie dużej ilości ludzie używają go źle, próbując zainicjować go z zewnątrz i śmieci. Jest to bardzo celowe dla wzoru, który sugeruję.


Dla tych, którzy nie chcą podążać za tym wzorem, może również działać dokładnie odwrotnie. Na początku wyeksportuj deklaracje do innej funkcji. Może nazwać to „właściwości” lub „publicProperties” lub coś w tym rodzaju. Następnie włóż resztę rzeczy do normalnego konstruktora.

„użyj ścisłego”;

klasa MyClass
{
    nieruchomości() {
        this.prop1 = „bla 1”;
        this.prop2 = 'bla 2';
        this.prop3 = 'bla 3';
    }

    konstruktor () {
        this.properties ();
        rób cokolwiek();
    }
}

Zauważ, że ta druga metoda może wyglądać na czystszą, ale ma również nieodłączny problem polegający na tym, że propertieszostaje zastąpiona, gdy jedna klasa za pomocą tej metody rozszerza inną. propertiesAby tego uniknąć, musisz podać więcej unikalnych nazw . Moja pierwsza metoda nie ma tego problemu, ponieważ jej fałszywa połowa konstruktora ma unikalną nazwę od klasy.

Jimbo Jonny
źródło
1
Nie używaj prototypowej metody nazwanej na cześć samej klasy. To nie jest idiomatyczne w JS, nie staraj się, aby wyglądało to na inny język. Jeśli naprawdę chcesz zastosować to podejście, kanoniczną nazwą metody jest init.
Bergi,
1
@Bergi - initjest często używanym wzorcem i często ma być wywoływany spoza klasy, gdy użytkownik zewnętrzny chce zainicjować, tj var b = new Thing(); b.init();. Jest to w 100% stylistyczny wybór, który wolałbym przekazać, że jest to druga funkcja, która jest automatycznie wywoływana przez wykorzystanie wzorców występujących w innych językach. O wiele mniej prawdopodobne jest, że ktoś na to spojrzy i przyjmie, że musi wywołać MyClassmetodę z zewnątrz, bardziej prawdopodobne, że uświadomi sobie, że intencją jest druga metoda działająca w budownictwie (tj. Wywoływana sama przez instancję).
Jimbo Jonny
Hm, mógłbym to zrozumieć patrząc na konstruktor, ale nie z nazwy metody MyClass.
Bergi,
1
@Bergi - Wzięcie wzorca z innego języka i zastosowanie go do JS w sposób, który nie jest technicznie tym, co się dzieje, ale nadal działa, nie jest całkowicie pozbawiony precedensu. Nie możesz mi powiedzieć, że nikt nie zauważył, że $myvarstandardowy sposób odwoływania się do zmiennych przeznaczonych do przechowywania obiektów jQuery nie jest dogodnie podobny do wzoru posiadania $ na początku zmiennych, do których przywykło tak wielu programistów PHP. Tylko ta mała implikacja, że ​​„tak, to nie jest dokładnie to samo… ale spójrz… to wciąż zmienna, ponieważ w ten sposób zmienne są wykonywane w niektórych językach!” pomaga
Jimbo Jonny
1
Wolę twoją ostatnią opcję z properties()funkcją. Jednak sprawy stają się nieco bardziej skomplikowane przy rozszerzaniu klas, więc sugerowałbym, że jeśli użyjesz properties()funkcji we wszystkich swoich klasach, aby zadeklarować swoje właściwości klasy, poprzedź nazwę metody nazwą klasy (IE: MyClassProperties()aby uniknąć przypadkowego zastąpienia wywołań funkcji w podklasach. Należy również pamiętać, że wszelkie wywołania funkcji super()muszą zostać zadeklarowane jako pierwsze w konstruktorze klas
TheDarkIn1978,
14

Co z oldschoolowym sposobem?

class MyClass {
     constructor(count){ 
          this.countVar = 1 + count;
     }
}
MyClass.prototype.foo = "foo";
MyClass.prototype.countVar = 0;

// ... 

var o1 = new MyClass(2); o2 = new MyClass(3);
o1.foo = "newFoo";

console.log( o1.foo,o2.foo);
console.log( o1.countVar,o2.countVar);

Konstruktor wymienia tylko te zmienne, które należy obliczyć. Lubię prototypowe dziedziczenie tej funkcji - może pomóc zaoszczędzić dużo pamięci (w przypadku, gdy istnieje wiele nigdy nieprzypisanych zmiennych).

zarkone
źródło
4
Nie oszczędza to pamięci i po prostu powoduje, że wydajność jest znacznie gorsza niż w przypadku zadeklarowania ich w konstruktorze. codereview.stackexchange.com/a/28360/9258
Esailija
2
Jest to także sprzeczne z celem używania klas ES6. W tej chwili wykorzystanie klas ES6 jako prawdziwych klas oop wydaje się niemożliwe, co jest nieco rozczarowujące ...
Kokodoko,
4
@Kokodoko real oop - masz na myśli, np. W Javie? Zgadzam się, zauważyłem, że wiele osób jest wściekłych na JS, ponieważ próbują używać go jak Java, tak jak się przyzwyczajają, ponieważ składnia JS wygląda podobnie i zakłada, że ​​działa w ten sam sposób ... Ale z w środku jest całkiem inaczej, jak wiemy.
zarkone
2
Nie chodzi jednak tylko o składnię języka. Filozofia OOP nadaje się do programowania ogólnie - szczególnie podczas tworzenia aplikacji i gier. JS tradycyjnie jest wdrażany w budowaniu stron internetowych, co jest zupełnie inne. W jakiś sposób te dwa podejścia muszą się ze sobą łączyć, ponieważ w Internecie coraz częściej pojawiają się również aplikacje.
Kokodoko
1
@Kokodoko Tylko dlatego, że jest to inny OOP, nie oznacza, że to nie jest OOP. Prototypy są w 100% uzasadnione w podejściu OOP; nikt nie będzie nazywał Self „non-OOP”, ponieważ używa prototypów. Brak dopasowania innego paradygmatu OOP oznacza po prostu: jest inny.
Dave Newton
13

Jak powiedział Benjamin w swojej odpowiedzi, TC39 wyraźnie postanowił nie uwzględniać tej funkcji przynajmniej w ES2015. Wydaje się jednak, że konsensus zostanie dodany w ES2016.

Składnia nie została jeszcze ustalona, ​​ale istnieje wstępna propozycja dla ES2016, która pozwoli zadeklarować właściwości statyczne w klasie.

Dzięki magii babel możesz tego dzisiaj używać. Włącz transformację właściwości klasy zgodnie z tymi instrukcjami i możesz zacząć. Oto przykład składni:

class foo {
  static myProp = 'bar'
  someFunction() {
    console.log(this.myProp)
  }
}

Ta propozycja jest na bardzo wczesnym etapie, więc przygotuj się na dostosowanie swojej składni w miarę upływu czasu.

Dąb Bonsai
źródło
Tak, to nie jest ES6. Jeśli nie wiesz, co to jest, nie powinieneś go używać.
Bergi,
10

[Długi wątek, nie jestem pewien, czy jest już wymieniony jako opcja ...].
Prostą alternatywą tylko dla kontyngentów byłoby zdefiniowanie stałej poza klasą. Będzie to dostępne tylko z samego modułu, chyba że towarzyszy mu getter.
W ten sposób prototypenie jest zaśmiecone i dostajesz const.

// will be accessible only from the module itself
const MY_CONST = 'string'; 
class MyClass {

    // optional, if external access is desired
    static get MY_CONST(){return MY_CONST;}

    // access example
    static someMethod(){
        console.log(MY_CONST);
    }
}
Hertzel Guinness
źródło
Co się stanie, jeśli a) użyjesz varzamiast const2) użyjesz wielu wystąpień tej klasy? Następnie zmienne zewnętrzne będą zmieniane z każdym wystąpieniem klasy
nick carraway
1
fail point @nickcarraway, moja oferta oznacza tylko const, a nie jak zatytułowane pytanie.
Hertzel Guinness
6

ES7 składnia członka klasy:

ES7ma rozwiązanie do „zbijania” funkcji konstruktora. Oto przykład:

class Car {
  
  wheels = 4;
  weight = 100;

}

const car = new Car();
console.log(car.wheels, car.weight);

Powyższy przykład wyglądałby następująco ES6:

class Car {

  constructor() {
    this.wheels = 4;
    this.weight = 100;
  }

}

const car = new Car();
console.log(car.wheels, car.weight);

Korzystając z tej opcji, pamiętaj, że ta składnia może nie być obsługiwana przez wszystkie przeglądarki i może być konieczna transpozycja wcześniejszej wersji JS.

Premia: fabryka obiektów:

function generateCar(wheels, weight) {

  class Car {

    constructor() {}

    wheels = wheels;
    weight = weight;

  }

  return new Car();

}


const car1 = generateCar(4, 50);
const car2 = generateCar(6, 100);

console.log(car1.wheels, car1.weight);
console.log(car2.wheels, car2.weight);

Willem van der Veen
źródło
3
Osiągnąłeś zmienne instancji, a nie zmienne klasy.
Tjad Clark
5

Możesz naśladować zachowanie klas es6 ... i używać zmiennych klas :)

Spójrz mamo ... żadnych zajęć!

// Helper
const $constructor = Symbol();
const $extends = (parent, child) =>
  Object.assign(Object.create(parent), child);
const $new = (object, ...args) => {
  let instance = Object.create(object);
  instance[$constructor].call(instance, ...args);
  return instance;
}
const $super = (parent, context, ...args) => {
  parent[$constructor].call(context, ...args)
}
// class
var Foo = {
  classVariable: true,

  // constructor
  [$constructor](who){
    this.me = who;
    this.species = 'fufel';
  },

  // methods
  identify(){
    return 'I am ' + this.me;
  }
}

// class extends Foo
var Bar = $extends(Foo, {

  // constructor
  [$constructor](who){
    $super(Foo, this, who);
    this.subtype = 'barashek';
  },

  // methods
  speak(){
    console.log('Hello, ' + this.identify());
  },
  bark(num){
    console.log('Woof');
  }
});

var a1 = $new(Foo, 'a1');
var b1 = $new(Bar, 'b1');
console.log(a1, b1);
console.log('b1.classVariable', b1.classVariable);

Położyłem to na GitHub

Ruslan
źródło
0

Sposób, w jaki to rozwiązałem, co jest kolejną opcją (jeśli masz dostępne jQuery), to Definiowanie pól w obiekcie starej szkoły, a następnie rozszerzenie klasy o ten obiekt. Nie chciałem też wysadzać konstruktora zadaniami, co wydawało się być dobrym rozwiązaniem.

function MyClassFields(){
    this.createdAt = new Date();
}

MyClassFields.prototype = {
    id : '',
    type : '',
    title : '',
    createdAt : null,
};

class MyClass {
    constructor() {
        $.extend(this,new MyClassFields());
    }
};

- Aktualizacja Po komentarzu Bergi.

Brak wersji JQuery:

class SavedSearch  {
    constructor() {
        Object.assign(this,{
            id : '',
            type : '',
            title : '',
            createdAt: new Date(),
        });

    }
}

Nadal masz konstruktora „grubego”, ale przynajmniej wszystko jest w jednej klasie i przypisane w jednym trafieniu.

EDYCJA 2: Teraz zatoczyłem pełne koło i teraz przypisuję wartości w konstruktorze, np

class SavedSearch  {
    constructor() {
        this.id = '';
        this.type = '';
        this.title = '';
        this.createdAt = new Date();
    }
}

Dlaczego? Naprawdę proste, korzystając z powyższego i niektórych komentarzy JSdoc, PHPStorm był w stanie wykonać uzupełnianie kodu we właściwościach. Przypisanie wszystkich zmiennych za jednym razem było przyjemne, ale niemożność kodowania uzupełnienia właściwości, imo, nie jest warta (prawie na pewno niewielkiej) poprawy wydajności.

Steve Childs
źródło
2
Jeśli potrafisz zrobić classskładnię, możesz to zrobić Object.assign. Nie potrzebujesz jQuery.
Bergi,
Nie widzę sensu tworzyć MyClassFieldskonstruktorów - nie ma żadnych metod. Czy potrafisz wyjaśnić, dlaczego to zrobiłeś (zamiast, powiedzmy, prostej funkcji fabrycznej, która zwraca dosłowność obiektu)?
Bergi,
@Bergi - Szczerze mówiąc, prawdopodobnie siła nawyku, a nie cokolwiek innego. Również fajny telefon o Object.assign - nie wiedziałem o tym!
Steve Childs,
0

Cóż, możesz zadeklarować zmienne w Konstruktorze.

class Foo {
    constructor() {
        var name = "foo"
        this.method = function() {
            return name
        }
    }
}

var foo = new Foo()

foo.method()
Osama Xäwãñz
źródło
1
Aby użyć tej zmiennej, musisz utworzyć instancję tej klasy. Funkcje statyczne nie mogą uzyskać dostępu do tej zmiennej
Aditya
0

Nadal nie możesz zadeklarować żadnych klas jak w innych językach programowania. Ale możesz utworzyć tyle zmiennych klas. Ale problemem jest zakres obiektu klasy. Więc według mnie, najlepszy sposób programowania OOP w ES6 Javascript: -

class foo{
   constructor(){
     //decalre your all variables
     this.MY_CONST = 3.14;
     this.x = 5;
     this.y = 7;
     // or call another method to declare more variables outside from constructor.
     // now create method level object reference and public level property
     this.MySelf = this;
     // you can also use var modifier rather than property but that is not working good
     let self = this.MySelf;
     //code ......... 
   }
   set MySelf(v){
      this.mySelf = v;
   }
   get MySelf(v){
      return this.mySelf;
   }
   myMethod(cd){
      // now use as object reference it in any method of class
      let self = this.MySelf;
      // now use self as object reference in code
   }
}
Tyler
źródło
-1

To jest trochę hackerskie połączenie static i get działa dla mnie

class ConstantThingy{
        static get NO_REENTER__INIT() {
            if(ConstantThingy._NO_REENTER__INIT== null){
                ConstantThingy._NO_REENTER__INIT = new ConstantThingy(false,true);
            }
            return ConstantThingy._NO_REENTER__INIT;
        }
}

gdzie indziej używane

var conf = ConstantThingy.NO_REENTER__INIT;
if(conf.init)...
TroyWorks
źródło
7
Polecam singleton_instancejako nazwę nieruchomości, aby wszyscy rozumieli, co tu robisz.
Bergi,