ES6 वर्ग चर विकल्प


491

वर्तमान में ES5 में हम में से कई लोग कक्षाओं और वर्ग चर बनाने के लिए चौखटे में निम्नलिखित पैटर्न का उपयोग कर रहे हैं, जो कि कम्फर्टेबल है:

// ES 5
FrameWork.Class({

    variable: 'string',
    variable2: true,

    init: function(){

    },

    addItem: function(){

    }

});

ES6 में आप मूल रूप से कक्षाएं बना सकते हैं, लेकिन कक्षा चर रखने का कोई विकल्प नहीं है:

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

अफसोस की बात है, ऊपर काम नहीं करेगा, क्योंकि कक्षाओं में केवल विधियाँ हो सकती हैं।

मैं समझता हूँ कि मैं यह कर सकते हैं this.myVar = trueमें constructor... लेकिन मैं विशेष रूप से जब मैं एक बड़ा वर्ग के लिए 20-30 + पैरामीटर है 'जंक' मेरे निर्माता, करने के लिए नहीं करना चाहती।

मैं इस मुद्दे को संभालने के कई तरीकों के बारे में सोच रहा था, लेकिन अभी तक कोई भी अच्छा नहीं मिला है। (उदाहरण के लिए: एक ClassConfigहैंडलर बनाएं , और एक parameterऑब्जेक्ट पास करें , जिसे क्लास से अलग घोषित किया जाता है। तब हैंडलर क्लास में जाता है। मैं WeakMapsकिसी तरह इंटीग्रेट करने के बारे में भी सोच रहा था ।)

इस स्थिति को संभालने के लिए आपको किस तरह के विचारों का सामना करना पड़ेगा?


1
आपकी मुख्य समस्या यह है कि आपके पास this.member = member20-30 मापदंडों के साथ अपने निर्माता पर दोहराव होगा ?
τίδηςιλος υουρα

1
क्या आप केवल public variable2 = trueकक्षा के तहत उपयोग नहीं कर सकते ? यह इसे प्रोटोटाइप पर परिभाषित करेगा।

14
@ Τίδηςιλος υουρα Yes: हाँ, और मैं भी आरंभिक प्रक्रियाओं के लिए अपने निर्माणकर्ता का उपयोग करना चाहता हूं न कि चर घोषणाओं के लिए।
विंटरकाउंटर

@derylius: यह मुख्य समस्या है, इसमें ऐसी सुविधा नहीं है। यहां तक ​​कि सार्वजनिक / निजी उपयोग भी अभी तक ES6 मसौदे में तय नहीं किया गया है। इसे एक टेस्ट स्पिन दें: es6fiddle.net
विंटरकाउंटर

नवीनतम के अनुसार, इसका यह कार्य है: wiki.ecmascript.org/doku.php?id=harmony:classes

जवाबों:


514

2018 अपडेट:

अब एक चरण 3 प्रस्ताव है - मैं कुछ महीनों में इस उत्तर को अप्रचलित बनाने के लिए तत्पर हूं।

इस बीच कोई भी टाइपस्क्रिप्ट या बैबल का उपयोग करके वाक्यविन्यास का उपयोग कर सकता है:

varName = value

एक वर्ग घोषणा / अभिव्यक्ति शरीर के अंदर और यह एक चर को परिभाषित करेगा। उम्मीद है कि कुछ महीनों / हफ्तों में मैं अपडेट पोस्ट कर सकूंगा।

अद्यतन: Chrome 74 अब इस सिंटैक्स के साथ काम कर रहा है।


ईएस 6 ( अधिकतम न्यूनतम कक्षाओं ) में प्रस्ताव के लिए ईएस विकी में नोट:

वहाँ (जानबूझकर) कोई प्रत्यक्ष घोषणात्मक तरीका नहीं है प्रोटोटाइप डेटा गुण (विधियों के अलावा) वर्ग गुण, या उदाहरण संपत्ति

घोषणा के बाहर वर्ग गुण और प्रोटोटाइप डेटा गुण बनाए जाने चाहिए।

एक वर्ग परिभाषा में निर्दिष्ट गुणों को उसी विशेषता के रूप में सौंपा गया है जैसे कि वे एक वस्तु शाब्दिक में दिखाई देते हैं।

इसका मतलब है कि आप जो पूछ रहे हैं उस पर विचार किया गया था, और स्पष्ट रूप से इसके खिलाफ फैसला किया गया था।

लेकिन क्यों?

अच्छा प्रश्न। TC39 के अच्छे लोग एक वर्ग की क्षमताओं को घोषित करने और परिभाषित करने के लिए वर्ग घोषणाएं करना चाहते हैं। इसके सदस्य नहीं। एक ES6 वर्ग घोषणा अपने उपयोगकर्ता के लिए अपने अनुबंध को परिभाषित करता है।

याद रखें, एक वर्ग परिभाषा प्रोटोटाइप विधियों को परिभाषित करती है - प्रोटोटाइप पर चर को परिभाषित करना आमतौर पर ऐसा कुछ नहीं है जो आप करते हैं। आप निश्चित रूप से उपयोग कर सकते हैं:

constructor(){
    this.foo = bar
}

कंस्ट्रक्टर में जैसा आपने सुझाव दिया। सर्वसम्मति का सारांश भी देखें ।

ईएस 7 और उससे आगे

ES7 के लिए एक नए प्रस्ताव पर काम किया जा रहा है जो वर्ग घोषणाओं और अभिव्यक्तियों के माध्यम से अधिक संक्षिप्त उदाहरण चर देता है - https://esdiscuss.org/topic/es7-property-initializers


4
@wintercounter से महत्वपूर्ण बात यह है कि परिभाषित करने की अनुमति देने के गुण उन्हें प्रोटोटाइप पर परिभाषित करते हैं, जैसे कि तरीकों और प्रत्येक उदाहरण के लिए नहीं। मैक्सिमली न्यूनतम कक्षाएं अभी भी बहुत ही मूल प्रोटोटाइपीय विरासत में हैं। आप वास्तव में अपने मामले में जो करना चाहते हैं वह है शेयर संरचना और प्रत्येक उदाहरण के लिए सदस्यों को असाइन करना। यह बस नहीं है कि ईएस 6 में कौन से वर्ग हैं - कार्यक्षमता साझा करना। तो हां, संरचना को साझा करने के लिए आपको पुराने वाक्यविन्यास से चिपके रहना होगा। ES7 तक कम से कम :)
बेंजामिन ग्रुएनबाम

5
आप staticसंपत्तियों का उल्लेख करना चाह सकते हैं
बरगी

8
उफ़, मस्तिष्क गोज़। मैं भूल गया कि staticकेवल तरीकों के लिए भी काम करता है।
बरगी

637
शायद TC39 के अच्छे लोगों को इस अवधारणा को "वर्ग" के अलावा कुछ और नाम देना चाहिए, अगर वे नहीं चाहते हैं कि यह बाकी प्रोग्रामिंग की तरह व्यवहार करे, "क्लास" नाम की किसी चीज़ से उम्मीद है।
एलेक्स

7
"क्लास फील्ड्स एंड स्टैटिक प्रॉपर्टीज़" प्रस्ताव भी देखें (पहले से ही बाबेल में लागू : github.com/jeffmo/es-class-fields-and-static-properties
मैट ब्राउन 6

127

बस बेंजामिन के जवाब में जोड़ने के लिए - वर्ग चर संभव हैं, लेकिन आप prototypeउन्हें सेट करने के लिए उपयोग नहीं करेंगे।

एक सच्चे वर्ग चर के लिए आप निम्नलिखित कुछ करना चाहेंगे:

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

एक वर्ग विधि के भीतर कि चर this.constructor.foo(या MyClass.foo) के रूप में पहुँचा जा सकता है ।

ये वर्ग गुण आमतौर पर वर्ग उदाहरण से सुलभ नहीं होंगे। यानी MyClass.fooदेता है 'bar'लेकिन new MyClass().fooहैundefined

यदि आप एक उदाहरण से अपने वर्ग चर तक भी पहुँच बनाना चाहते हैं, तो आपको अतिरिक्त रूप से एक गटर को परिभाषित करना होगा:

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

MyClass.foo = 'bar';

मैंने केवल ट्रेसेर के साथ इसका परीक्षण किया है, लेकिन मेरा मानना ​​है कि यह मानक कार्यान्वयन में समान काम करेगा।

जावास्क्रिप्ट वास्तव में कक्षाएं नहीं है । ईएस 6 के साथ भी हम एक क्लास-आधारित भाषा के बजाय एक ऑब्जेक्ट- या प्रोटोटाइप-आधारित भाषा देख रहे हैं। किसी में function X () {}, X.prototype.constructorवापस इंगित करता है X। जब newऑपरेटर का उपयोग किया जाता है X, तो विरासत में एक नई वस्तु बनाई जाती है X.prototype। उस नई वस्तु (सहित ) में कोई अपरिभाषित गुण constructorवहाँ से देखा जाता है। हम इसे वस्तु और वर्ग गुण उत्पन्न करने के बारे में सोच सकते हैं।


29

बाबेल ESNext में वर्ग चर का समर्थन करता है, इस उदाहरण की जाँच करें :

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'

1
आप कर सकते हैं बार एक निजी इस तरह "#" के साथ यह बहाना बनाकर वर्ग चर: #bar = 2;
लोनी बेस्ट

26

आपके उदाहरण में:

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

MY_CONST के कारण आदिम https://developer.mozilla.org/en-US/docs/Glossary/Primitive है जो हम अभी कर सकते हैं:

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

लेकिन अगर MY_CONSTसंदर्भ प्रकार है जैसे static get MY_CONST() {return ['string'];}चेतावनी आउटपुट स्ट्रिंग, गलत है । ऐसे मामले मेंdelete ऑपरेटर चाल कर सकता है:

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

और अंत में वर्ग चर के लिए नहीं 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

5
कृपया deleteप्रदर्शन कारणों से अकेले ऑपरेटर से बचें । आप वास्तव में यहाँ क्या चाहते हैं Object.defineProperty
बरगी

@ शिनज़ौ मैं वही सोच रहा था। हालांकि ओपी की गलती जरूरी नहीं है; यह वास्तव में ऐसी भाषा है जिसमें डेटा का प्रतिनिधित्व करने के लिए उचित तंत्र का अभाव है जो उसके वास्तविक विश्व संबंधों को दर्शाता है।
user1974458

17

चूंकि आपका मुद्दा ज्यादातर शैलीगत है (घोषणाओं के एक समूह के साथ कंस्ट्रक्टर को भरना नहीं चाहता है) यह स्टाइलिस्टिक रूप से भी हल किया जा सकता है।

जिस तरह से मैं इसे देखता हूं, कई वर्ग आधारित भाषाओं में कंस्ट्रक्टर एक फ़ंक्शन होता है जिसे क्लास नाम के नाम पर रखा जाता है। Stylistically हम इसका उपयोग कर सकते हैं कि ES6 वर्ग बनाने के लिए जो स्टाइलिस्टिक रूप से अभी भी समझ में आता है, लेकिन निर्माणकर्ता में होने वाले विशिष्ट कार्यों को उन सभी संपत्ति घोषणाओं के साथ समूहित नहीं करता है जो हम कर रहे हैं। हम केवल वास्तविक जेएस कंस्ट्रक्टर को "घोषणा क्षेत्र" के रूप में उपयोग करते हैं, फिर एक क्लास फंक्शन बनाते हैं जिसे हम अन्यथा "अन्य कंस्ट्रक्टर स्टफ" क्षेत्र के रूप में मानते हैं, इसे सच्चे कंस्ट्रक्टर के अंत में कहते हैं।

"सख्त का उपयोग करें";

वर्ग MyClass
{
    // केवल अपने गुणों की घोषणा करें और फिर इसे कॉल करें। ClassName (); यहां से
    निर्माता () {
        this.prop1 = 'blah 1';
        this.prop2 = 'blah 2';
        this.prop3 = 'blah 3';
        this.MyClass ();
    }

    // सभी प्रकार के अन्य "कंस्ट्रक्टर" सामान, अब घोषणाओं के साथ उछला नहीं
    मेरी कक्षा() {
        कुछ भी करें();
    }
}

दोनों का निर्माण नई आवृत्ति के रूप में किया जाएगा।

2 कंस्ट्रक्टर जैसे कि आप घोषणाओं को अलग करते हैं और अन्य रचनाकार एक्शन जिन्हें आप लेना चाहते हैं, और शैलीगत रूप से यह समझना बहुत मुश्किल नहीं है कि क्या चल रहा है।

मुझे पता है कि बहुत सी घोषणाओं और / या तात्कालिकता पर होने वाली बहुत सी क्रियाओं और दो विचारों को एक दूसरे से अलग रखने के लिए उपयोग करने के लिए उपयोग करने के लिए यह एक अच्छी शैली है।


ध्यान दें : मैं बहुत उद्देश्यपूर्ण "इनिशियलाइज़िंग" ( init()या एक initialize()विधि की तरह ) के विशिष्ट मुहावरेदार विचारों का उपयोग नहीं करता क्योंकि वे अक्सर अलग तरह से उपयोग किए जाते हैं। निर्माण और आरंभ के विचार के बीच एक प्रकार का अनुमान है। कंस्ट्रक्टर के साथ काम करने वाले लोगों को पता है कि वे स्वचालित रूप से तात्कालिकता के हिस्से के रूप में कहे जाते हैं। एक initविधि को देखकर बहुत से लोग दूसरी नज़र के बिना यह मानने वाले हैं कि उन्हें कुछ ऐसा करने की आवश्यकता है var mc = MyClass(); mc.init();, क्योंकि यह है कि आप आमतौर पर किस तरह का उपयोग करते हैं। मैं वर्ग के उपयोगकर्ता के लिए एक आरंभीकरण प्रक्रिया जोड़ने की कोशिश कर नहीं कर रहा हूँ, मैं जोड़ने के लिए कोशिश कर रहा हूँ करने के लिए वर्ग के ही निर्माण की प्रक्रिया।

हालांकि कुछ लोग एक पल के लिए डबल-टेक कर सकते हैं, यह वास्तव में बिंदु का हिस्सा होता है: यह उन्हें सूचित करता है कि इरादे निर्माण का हिस्सा है, भले ही यह उन्हें थोड़ा सा लेने और जाने के लिए "नहीं है" ईएस 6 कंस्ट्रक्टर कैसे काम करते हैं "और वास्तविक कंस्ट्रक्टर को देखने के लिए एक दूसरे को देखते हैं" ओह, वे इसे नीचे कहते हैं, मैं देखता हूं ", यह उस इरादे (या गलत तरीके से इसे संप्रेषित करने) से बेहतर नहीं है और शायद बहुत अधिक हो रहा है लोग इसका गलत उपयोग करते हैं, इसे बाहर और कबाड़ से शुरू करने की कोशिश कर रहे हैं। मेरे द्वारा सुझाए गए पैटर्न के लिए यह बहुत ही जानबूझकर है।


जो लोग उस पैटर्न का पालन नहीं करना चाहते हैं, उनके लिए सटीक विपरीत भी काम कर सकता है। शुरुआत में एक और समारोह के लिए घोषणाओं को खेत। शायद इसे "गुण" या "publicProperties" या कुछ और नाम दें। फिर बाकी सामान को सामान्य कंस्ट्रक्टर में डालें।

"सख्त का उपयोग करें";

वर्ग MyClass
{
    गुण() {
        this.prop1 = 'blah 1';
        this.prop2 = 'blah 2';
        this.prop3 = 'blah 3';
    }

    कंस्ट्रक्टर () {
        this.properties ();
        कुछ भी करें();
    }
}

ध्यान दें कि यह दूसरी विधि क्लीनर लग सकती है, लेकिन इसमें एक अंतर्निहित समस्या भी है, जहां propertiesइस पद्धति का उपयोग करने वाले एक वर्ग के रूप में ओवरराइड हो जाता है। इससे propertiesबचने के लिए आपको अधिक विशिष्ट नाम देने होंगे । मेरी पहली विधि में यह समस्या नहीं है क्योंकि इसके निर्माता का फर्जी आधा वर्ग के नाम पर विशिष्ट है।


1
कृपया कक्षा के नाम पर एक प्रोटोटाइप पद्धति का उपयोग न करें। जेएस में यह गैर-मुहावरेदार है, इसे किसी अन्य भाषा की तरह बनाने की कोशिश न करें। यदि आप वास्तव में इस दृष्टिकोण का उपयोग करना चाहते हैं, तो विधि के लिए विहित नाम है init
बरगी

1
@ बर्गी - initएक ऐसा पैटर्न है जिसका उपयोग अक्सर किया जाता है, और अक्सर इसका मतलब कक्षा के बाहर से कॉल किया जाता है जब बाहरी उपयोगकर्ता प्रारंभ करना चाहता है, अर्थात var b = new Thing(); b.init();। यह एक 100% शैलीगत विकल्प है जिसे मैं संवाद करना पसंद करूंगा कि यह एक दूसरा फ़ंक्शन है जो अन्य भाषाओं में पाए गए पैटर्न का लाभ उठाकर स्वचालित रूप से कहा जाता है। यह बहुत कम संभावना है कि कोई इसे देखेगा और यह मान लेगा कि उन्हें MyClassबाहर से विधि को कॉल करने की आवश्यकता है , अधिक संभावना है कि वे इरादे को महसूस करेंगे कि निर्माण में अभिनय करने का एक दूसरा तरीका है (यानी इंस्टेंटेशन पर खुद कहा जाता है)।
जिम्बो जॉनी

हम्म, मुझे एहसास हो सकता है कि कंस्ट्रक्टर को देखकर, लेकिन विधि के नाम से नहीं MyClass
बरगी

1
@ बर्गी - दूसरी भाषा से एक पैटर्न लेना और इसे जेएस में लागू करना एक ऐसा तरीका है जो तकनीकी रूप से नहीं है, लेकिन फिर भी काम पूरी तरह से मिसाल के बिना नहीं है। आप मुझे यह नहीं बता सकते कि किसी ने भी ध्यान नहीं दिया है कि $myvarjQuery ऑब्जेक्ट्स को रखने के लिए बनाए गए वेरिएबल्स का उल्लेख करने का मानक तरीका वेरिएबल्स की शुरुआत में $ होने के पैटर्न के समान सुविधाजनक नहीं है, जिसके लिए कई PHP प्रोग्रामर का उपयोग किया जाता है। बस थोड़ा सा निहितार्थ है कि "हाँ, यह वही सटीक बात नहीं है ... लेकिन देखो ... यह अभी भी एक चर है क्योंकि यह एक तरह से चर कुछ भाषाओं में किया जाता है!" मदद करता है।
जिम्बो जॉनी

1
मैं properties()फ़ंक्शन के साथ आपका अंतिम विकल्प पसंद करता हूं । हालाँकि, कक्षाओं को बढ़ाते समय चीजें थोड़ी अधिक जटिल हो जाती हैं, इसलिए मैं आपको सुझाव दूंगा कि यदि आप properties()अपनी सभी कक्षाओं में एक फ़ंक्शन का उपयोग करते हुए आपको वर्ग गुण घोषित करते हैं कि आप वर्ग नाम के साथ विधि का नाम उपसर्ग करते हैं (IE: MyClassProperties()क्रम में ओवरराइडिंग से बचने के लिए फ़ंक्शन उप-कक्षाओं के भीतर कॉल करता है। इसके अलावा, ध्यान रखें कि किसी भी कॉल को super()पहले क्लास कंस्ट्रक्टर में घोषित किया जाना चाहिए।
TheDarkIn1978

14

ओल्डस्कूल रास्ते के बारे में क्या?

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);

कंस्ट्रक्टर में आप केवल उन वर्सेस का उल्लेख करते हैं, जिनकी गणना की जानी है। मुझे इस फीचर के लिए प्रोटोटाइप इनहेरिटेंस पसंद है - यह बहुत सारी मेमोरी (अगर कभी-कभी असाइन किए गए वेरिएंट नहीं हैं तो) को बचाने में मदद कर सकता है।


4
यह स्मृति को नहीं बचाता है और यह सिर्फ प्रदर्शन को बहुत खराब करता है अगर आपने उन्हें निर्माणकर्ता में घोषित किया था। codereview.stackexchange.com/a/28360/9258
Esailija

2
इसके अलावा, यह पहले स्थान पर ES6 वर्गों का उपयोग करने के उद्देश्य को पराजित करता है। जैसा कि यह खड़ा है, शायद ही ऐसा लगता है कि ईएस 6 कक्षाओं का उपयोग करना संभव है जैसे कि असली ऊप कक्षाएं, जो कुछ हद तक निराशाजनक है ...
कोकोडोको

4
@ Kokodoko असली ऊप - आप मतलब है, जैसे जावा में? मैं सहमत हूं, मैंने देखा है कि बहुत से लोग जेएस से नाराज़ हैं क्योंकि वे इसे जावा की तरह इस्तेमाल करने की कोशिश करते हैं, जैसे उन्हें आदत होती है, क्योंकि जेएस सिंटैक्स समान दिखता है, और वे मानते हैं कि यह उसी तरह काम करता है ... लेकिन से अंदर, यह काफी भिन्न है, जैसा कि हम जानते हैं।
झारकॉन

2
हालांकि यह केवल भाषा वाक्य रचना के बारे में नहीं है। ओओपी दर्शन सामान्य रूप से प्रोग्रामिंग के लिए खुद को बहुत अच्छी तरह से उधार देता है - खासकर जब एप्लिकेशन और गेम बनाते हैं। जेएस को पारंपरिक रूप से वेबपेज बनाने में लागू किया गया है जो काफी अलग है। किसी तरह उन दो दृष्टिकोणों को एक साथ आने की जरूरत है, क्योंकि वेब ऐप्स के बारे में भी अधिक हो रहा है।
कोकोडोको

1
@Kokodoko सिर्फ इसलिए कि यह एक अलग OOP है इसका मतलब यह नहीं है कि यह OOP नहीं है । प्रोटोटाइप 100%-ओवलिड ओओपी दृष्टिकोण हैं; कोई भी स्वयं को "गैर-ओओपी" कहने वाला नहीं है क्योंकि यह प्रोटोटाइप का उपयोग करता है। एक और OOP प्रतिमान से मेल न खाने का मतलब है कि: यह अलग है।
डेव न्यूटन

13

जैसा कि बेंजामिन ने अपने जवाब में कहा, TC39 ने स्पष्ट रूप से इस सुविधा को कम से कम ES2015 के लिए शामिल नहीं करने का फैसला किया। हालाँकि, सर्वसम्मति से लगता है कि वे इसे ES2016 में शामिल करेंगे।

वाक्यविन्यास अभी तक तय नहीं किया गया है, लेकिन ES2016 के लिए एक प्रारंभिक प्रस्ताव है जो आपको एक वर्ग पर स्थिर गुणों की घोषणा करने की अनुमति देगा।

बैबल के जादू के लिए धन्यवाद, आप आज इसका उपयोग कर सकते हैं। इन निर्देशों के अनुसार वर्ग गुणों को बदलने में सक्षम करें और आप जाने के लिए अच्छे हैं। यहाँ वाक्य रचना का एक उदाहरण दिया गया है:

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

यह प्रस्ताव बहुत प्रारंभिक अवस्था में है, इसलिए समय बीतने के साथ-साथ अपने वाक्यविन्यास को तैयार करने के लिए तैयार रहें।


हाँ, यह ES6 नहीं है। जब तक आप नहीं जानते कि यह क्या है, आपको इसका उपयोग नहीं करना चाहिए।
बर्गी

10

[लंबा धागा, सुनिश्चित नहीं है कि अगर यह पहले से ही एक विकल्प के रूप में सूचीबद्ध है ...]। केवल प्रतियोगियों के लिए
एक सरल विकल्प , वर्ग के बाहर कांस्ट को परिभाषित करना होगा। यह केवल मॉड्यूल से ही सुलभ होगा, जब तक कि एक गेटर के साथ नहीं। इस तरह से फिसड्डी नहीं है और आप प्राप्त करते हैं ।
prototypeconst

// 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);
    }
}

यदि आप क) 2 के varबजाय const) इस वर्ग के कई उदाहरणों का उपयोग करते हैं तो क्या होगा ? तब बाहरी चर को कक्षा के प्रत्येक उदाहरण के साथ बदल दिया जाएगा
निक कैरवे

1
फेल पॉइंट @nickcarraway, मेरा प्रस्ताव केवल कास्ट के लिए खड़ा है, न कि प्रश्न के शीर्षक के रूप में।
हर्ट्ज़ेल गिनीज

6

ES7 वर्ग के सदस्य वाक्य रचना:

ES7आपके निर्माता फ़ंक्शन को 'जंक करने' के लिए एक समाधान है। यहाँ एक उदाहरण है:

class Car {
  
  wheels = 4;
  weight = 100;

}

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

उपरोक्त उदाहरण निम्नलिखित में दिखेगा ES6:

class Car {

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

}

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

इस का उपयोग करते समय अवगत रहें कि यह वाक्यविन्यास सभी ब्राउज़रों द्वारा समर्थित नहीं हो सकता है और जेएस के पुराने संस्करण को ट्रांसप्लान्ट करना पड़ सकता है।

बोनस: एक वस्तु कारखाना:

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);


3
आपने उदाहरण चर को पूरा किया है, वर्ग चर को नहीं।
तजाद क्लार्क

5

आप es6 वर्गों के व्यवहार की नकल कर सकते हैं ... और अपने वर्ग चर का उपयोग करें :)

देखो मम्मी ... कोई क्लास नहीं!

// 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);

मैंने इसे GitHub पर रखा


0

जिस तरह से मैंने इसे हल किया, जो एक और विकल्प है (यदि आपके पास jQuery उपलब्ध है), एक पुराने स्कूल के ऑब्जेक्ट में फ़ील्ड्स को परिभाषित करना और फिर उस ऑब्जेक्ट के साथ कक्षा का विस्तार करना था। मैं असाइनमेंट के साथ कंस्ट्रक्टर को काली मिर्च नहीं देना चाहता था, यह एक साफ समाधान था।

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

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

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

- बरगी की टिप्पणी के बाद अपडेट करें।

कोई JQuery संस्करण:

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

    }
}

आप अभी भी 'वसा' निर्माता के साथ अंत करते हैं, लेकिन कम से कम एक कक्षा में इसके सभी और एक हिट में सौंपा गया है।

EDIT # 2: मैं अब पूरा चक्कर लगा चुका हूं और अब कंस्ट्रक्टर में मान दे रहा हूं, जैसे

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

क्यों? सरल रूप से, ऊपर से कुछ JSdoc टिप्पणियों का उपयोग करते हुए, PHPStorm गुणों पर कोड पूरा करने में सक्षम था। एक हिट में सभी वेरिएस को असाइन करना अच्छा था, लेकिन गुण, इमो को पूरा करने में असमर्थता, लगभग (निश्चित रूप से माइनसक्यूल) प्रदर्शन लाभ के लायक नहीं है।


2
यदि आप classवाक्य रचना कर सकते हैं , तो आप भी कर सकते हैं Object.assign। JQuery की कोई जरूरत नहीं
बेरी

मुझे MyClassFieldsकंस्ट्रक्टर बनाने के लिए कोई बिंदु नहीं दिख रहा है - इसका कोई तरीका नहीं है। क्या आप यह बता सकते हैं कि आपने ऐसा क्यों किया (इसके बजाय, एक साधारण फैक्ट्री फ़ंक्शन जो एक वस्तु शाब्दिक रिटर्न देता है)?
बर्गी

@ बरगी - ईमानदार होने के बजाए आदत के बल पर संभव है। Object.assign के बारे में भी अच्छी कॉल - उस के बारे में पता नहीं था!
स्टीव

0

खैर, आप कंस्ट्रक्टर के अंदर वैरिएबल घोषित कर सकते हैं।

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

var foo = new Foo()

foo.method()

1
आपको इस चर का उपयोग करने के लिए इस वर्ग का एक उदाहरण बनाने की आवश्यकता होगी। स्टेटिक फ़ंक्शंस उस वैरिएबल तक नहीं पहुँच सकते
आदित्य

0

फिर भी आप अन्य कक्षाओं की तरह किसी अन्य प्रोग्रामिंग भाषाओं में घोषित नहीं कर सकते। लेकिन आप कई वर्ग चर बना सकते हैं। लेकिन समस्या वर्ग वस्तु का दायरा है। तो मेरे अनुसार, ES6 जावास्क्रिप्ट में OOP प्रोग्रामिंग का सबसे अच्छा तरीका: -

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
   }
}

-1

यह स्टेटिक का थोड़ा सा हैकॉश कॉम्बो है और मेरे लिए काम करता है

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;
        }
}

अन्यत्र उपयोग किया जाता है

var conf = ConstantThingy.NO_REENTER__INIT;
if(conf.init)...

7
मैं singleton_instanceएक प्रॉपर्टी के नाम की सिफारिश करूंगा ताकि हर कोई यह समझ सके कि आप यहां क्या कर रहे हैं।
बरगी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.