ES6 कक्षाओं में स्थिर स्थिरांक की घोषणा?


311

मैं एक में स्थिरांक को लागू करना चाहता हूं class, क्योंकि यह वह जगह है जहां उन्हें कोड में पता लगाने के लिए समझ में आता है।

अब तक, मैं स्टैटिक विधियों के साथ निम्नलिखित वर्कअराउंड को लागू कर रहा हूं:

class MyClass {
    static constant1() { return 33; }
    static constant2() { return 2; }
    // ...
}

मुझे पता है कि प्रोटोटाइप के साथ फील करने की संभावना है, लेकिन कई इसके खिलाफ सलाह देते हैं।

ईएस 6 कक्षाओं में स्थिरांक को लागू करने का एक बेहतर तरीका है?


7
व्यक्तिगत रूप से मैं सिर्फ अपरकेस वर्सेज का उपयोग करता हूं, और अपने आप को उन्हें नहीं छूने के लिए कहता हूं;)
जूनियर

3
@twicejr मुझे लगता है कि यह समान नहीं है, क्योंकि स्टैटिक वैरिएबल को उस क्लास के ऑब्जेक्ट को तुरंत इंस्टेंट किए बिना एक्सेस किया जा सकता है?
लुकास मॉर्गन

जवाबों:


385

यहाँ कुछ चीजें हैं जो आप कर सकते हैं:

मॉड्यूलconst से निर्यात करें । आपके उपयोग के मामले के आधार पर, आप बस:

export const constant1 = 33;

और उस मॉड्यूल से आयात करें जहां आवश्यक हो। या, अपने स्थिर विधि विचार पर निर्माण, तो आप एक की घोषणा कर सकता है static प्राप्त एक्सेसर :

const constant1 = 33,
      constant2 = 2;
class Example {

  static get constant1() {
    return constant1;
  }

  static get constant2() {
    return constant2;
  }
}

इस तरह, आपको कोष्ठक की आवश्यकता नहीं होगी:

const one = Example.constant1;

बैबल REPL उदाहरण

फिर, जैसा कि आप कहते हैं, चूँकि एक classफ़ंक्शन के लिए सिंटैक्टिक शुगर है , इसलिए आप केवल एक गैर-योग्य संपत्ति जोड़ सकते हैं:

class Example {
}
Object.defineProperty(Example, 'constant1', {
    value: 33,
    writable : false,
    enumerable : true,
    configurable : false
});
Example.constant1; // 33
Example.constant1 = 15; // TypeError

यह अच्छा हो सकता है अगर हम ऐसा कुछ कर सकते हैं:

class Example {
    static const constant1 = 33;
}

लेकिन दुर्भाग्य से यह वर्ग संपत्ति सिंटैक्स केवल ES7 प्रस्ताव में है, और तब भी यह constसंपत्ति को जोड़ने की अनुमति नहीं देगा ।


क्या ऐसी कोई पुष्टि है कि स्थैतिक गुणों को इस तरह की चीजों के लिए एक बार गणना की जाती है, या क्या यह IIFE का उपयोग करने के लिए सुरक्षित है और रिटर्न मूल्यों के बार-बार निर्माण से बचने के लिए IIFE में मैन्युअल रूप से संपत्ति जोड़ते हैं। मुझे चिंता है कि अगर 100000 प्रविष्टि JSObject की तरह, अगर रिटर का परिणाम वास्तव में भारी है, तो हर बार रिक्टर को कॉल करने के लिए खराब गेट्टर का निर्माण करना होगा। प्रदर्शन के आधार पर इसका परीक्षण करना आसान है। हालांकि, यह अलग-अलग तरीके से लागू किया जा सकता है, इसके निश्चित रूप से उन्नत निर्णयों के बजाय प्राप्तकर्ताओं को लागू करना आसान है, भले ही यह निरंतर हो या न हो।
दिमित्री

3
जबकि ऊपर चतुराई से एक वर्ग के लिए एक निरंतर संपत्ति जोड़ता है, निरंतर के लिए वास्तविक मान "वर्ग परिभाषा" {} "के बाहर है, जो वास्तव में एनकैप्सुलेशन की परिभाषाओं में से एक का उल्लंघन करता है। मुझे लगता है कि यह केवल एक स्थिर संपत्ति को "अंदर" परिभाषित करने के लिए पर्याप्त है और इस मामले में प्राप्त करने की कोई आवश्यकता नहीं है।
NoChance

1
@NoChance अच्छे अंक। वह सिर्फ दृष्टांत था। कोई कारण नहीं है कि यदि आवश्यक हो तो गेट्टर विधि पूरी तरह से मूल्य को एनकैप्सुलेट नहीं कर सकती है।
कोडिंगइंट्रीग्यू

ES7 प्रस्ताव का उपयोग करने के लिए तत्पर है क्योंकि यह मुझे अधिक प्राकृतिक और OO भाषाओं के बहुमत के बराबर दिखता है।
संगमा

क्या मैं निरंतर एक उदाहरण चर घोषित करना चाहते हैं? क्या मैं कुछ ऐसा कर सकता हूंthis.defineProperty(this, 'constant1', {...})
फ्रांसेस्को बोई

33
class Whatever {
    static get MyConst() { return 10; }
}

let a = Whatever.MyConst;

लगता है मेरे लिए काम करता है।


क्या यह सामान्य तरीके से कक्षा के अंदर पहुंच सकता है?
PirateApp

3
@PirateApp आप इसे कक्षा के एक उदाहरण के अंदर से भी एक स्थिर विधि के रूप में उपयोग कर सकते हैं। हालाँकि, चूंकि यह स्थिर है आप this.MyConstकिसी Whateverउदाहरण के अंदर से उपयोग नहीं कर सकते हैं , आपको हमेशा इसे इस तरह लिखना होगा: Whatever.MyConst
TheDarkIn1978

23

मैं उपयोग कर रहा हूं babelऔर निम्नलिखित सिंटैक्स मेरे लिए काम कर रहा है:

class MyClass {
    static constant1 = 33;
    static constant2 = {
       case1: 1,
       case2: 2,
    };
    // ...
}

MyClass.constant1 === 33
MyClass.constant2.case1 === 1

कृपया विचार करें कि आपको पूर्व निर्धारित की आवश्यकता है "stage-0"
इसे स्थापित करने के लिए:

npm install --save-dev babel-preset-stage-0

// in .babelrc
{
    "presets": ["stage-0"]
}

अपडेट करें:

वर्तमान में उपयोग करें stage-3


21
समस्या यह है कि निरंतर आश्वस्त है। सेशन नहीं चाहता कि
CodingIntrigue

3
FYI करें, यह अब babelstage-2
bmaupin

3
वे निरंतर नहीं हैं
डेव एल।

1
@ कोडिंगइंट्रीग्यू क्या Object.freeze()क्लास को ठीक करेगा?
एंटीमनी

1
@Antimony मैंने ऐसा परीक्षण नहीं किया है, लेकिन मुझे ऐसा लगता है। समस्या यह है कि यह वर्ग के सभी गुणों पर लागू होगी। गैर-स्थिर भी।
कोडिंगइंट्रीग्यू

14

में इस दस्तावेज़ में यह कहा गया है:

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

इसका मतलब है कि यह जानबूझकर ऐसा है।

शायद आप कंस्ट्रक्टर में एक चर को परिभाषित कर सकते हैं?

constructor(){
    this.key = value
}

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

1
स्थिरांक अपरिवर्तनीय होना चाहिए। निर्माण के दौरान ऑब्जेक्ट पर गुणों को असाइन करने से ऐसे गुण मिलेंगे जो संशोधित किए जा सकते हैं।
दर्शन

11

Object.freezeइसे अपरिवर्तनीय बनाने के लिए आप पर क्लास (es6) / कंस्ट्रक्टर फंक्शन (es5) ऑब्जेक्ट का उपयोग करना भी संभव है :

class MyConstants {}
MyConstants.staticValue = 3;
MyConstants.staticMethod = function() {
  return 4;
}
Object.freeze(MyConstants);
// after the freeze, any attempts of altering the MyConstants class will have no result
// (either trying to alter, add or delete a property)
MyConstants.staticValue === 3; // true
MyConstants.staticValue = 55; // will have no effect
MyConstants.staticValue === 3; // true

MyConstants.otherStaticValue = "other" // will have no effect
MyConstants.otherStaticValue === undefined // true

delete MyConstants.staticMethod // false
typeof(MyConstants.staticMethod) === "function" // true

कक्षा को बदलने की कोशिश करने से आपको एक नरम-असफलता मिलेगी (किसी भी त्रुटि को नहीं फेंकेंगे, इसका बस कोई प्रभाव नहीं होगा)।


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

मैं Object.freeze()अपरिवर्तनीयता को लागू करने के लिए प्यार करता हूं , और हाल ही में इसका उपयोग कर रहा हूं । बस इसे पुनरावर्ती रूप से लागू करने के लिए मत भूलना!
jeffwtribble

6

शायद बस अपने सभी स्थिरांक को एक जमे हुए वस्तु में डाल दें?

class MyClass {

    constructor() {
        this.constants = Object.freeze({
            constant1: 33,
            constant2: 2,
        });
    }

    static get constant1() {
        return this.constants.constant1;
    }

    doThisAndThat() {
        //...
        let value = this.constants.constant2;
        //...
    }
}

स्थिर फ़ंक्शन चर 'इस' का उपयोग नहीं कर सकता है।
पोकरफैस

4

जैसे https://stackoverflow.com/users/2784136/rodrigo-botti ने कहा, मुझे लगता है कि आप ढूंढ रहे हैं Object.freeze()। यहाँ अपरिवर्तनीय सांख्यिकी के साथ एक वर्ग का एक उदाहरण दिया गया है:

class User {
  constructor(username, age) {
    if (age < User.minimumAge) {
      throw new Error('You are too young to be here!');
    }
    this.username = username;
    this.age = age;
    this.state = 'active';
  }
}

User.minimumAge = 16;
User.validStates = ['active', 'inactive', 'archived'];

deepFreeze(User);

function deepFreeze(value) {
  if (typeof value === 'object' && value !== null) {
    Object.freeze(value);
    Object.getOwnPropertyNames(value).forEach(property => {
      deepFreeze(value[property]);
    });
  }
  return value;
}

1

यहाँ एक और तरीका है जो आप कर सकते हैं

/*
one more way of declaring constants in a class,
Note - the constants have to be declared after the class is defined
*/
class Auto{
   //other methods
}
Auto.CONSTANT1 = "const1";
Auto.CONSTANT2 = "const2";

console.log(Auto.CONSTANT1)
console.log(Auto.CONSTANT2);

नोट - आदेश महत्वपूर्ण है, आप ऊपर स्थिरांक नहीं रख सकते

उपयोग कंसोल.लॉग (Auto.CONSTANT1);


5
हालांकि वे अपरिवर्तनीय नहीं हैं
जॉन हार्डिंग

1

आप ES6 कक्षाओं की एक विषम विशेषता का उपयोग करके एक वर्ग पर स्थिर स्थिरांक को परिभाषित करने का एक तरीका बना सकते हैं। चूंकि स्टैटिक्स उनके उपवर्गों द्वारा विरासत में मिले हैं, आप निम्न कार्य कर सकते हैं:

const withConsts = (map, BaseClass = Object) => {
  class ConstClass extends BaseClass { }
  Object.keys(map).forEach(key => {
    Object.defineProperty(ConstClass, key, {
      value: map[key],
      writable : false,
      enumerable : true,
      configurable : false
    });
  });
  return ConstClass;
};

class MyClass extends withConsts({ MY_CONST: 'this is defined' }) {
  foo() {
    console.log(MyClass.MY_CONST);
  }
}

1

आप कक्षा को फ्रीज करके "स्थिरांक" केवल-पढ़ने योग्य (अपरिवर्तनीय) बना सकते हैं। जैसे

class Foo {
    static BAR = "bat"; //public static read-only
}

Object.freeze(Foo); 

/*
Uncaught TypeError: Cannot assign to read only property 'BAR' of function 'class Foo {
    static BAR = "bat"; //public static read-only
}'
*/
Foo.BAR = "wut";

0

यदि आप फ़ंक्शन और क्लास सिंटैक्स के बीच मिश्रण और मिलान करने में सहज हैं, तो आप कक्षा के बाद स्थिरांक घोषित कर सकते हैं (स्थिरांक 'उठा लिया जाता है')। ध्यान दें कि विज़ुअल स्टूडियो कोड मिश्रित सिंटैक्स को ऑटो-फ़ॉर्मेट करने के लिए संघर्ष करेगा, (हालांकि यह काम करता है)।

class MyClass {
    // ...

}
MyClass.prototype.consts = { 
    constant1:  33,
    constant2: 32
};
mc = new MyClass();
console.log(mc.consts.constant2);    


0

इसे मैने किया है।

class Circle
{
    constuctor(radius)
    {
        this.radius = radius;
    }
    static get PI()
    {
        return 3.14159;
    }
}

PI का मान किसी कार्य से लौटाए जाने के बाद से बदला जाने से सुरक्षित है। आप इसे Circle.PI के माध्यम से एक्सेस कर सकते हैं। इसे असाइन करने का कोई भी प्रयास केवल [] के माध्यम से एक स्ट्रिंग चरित्र को निर्दिष्ट करने के प्रयास के समान तरीके से फर्श पर गिरा दिया जाता है।


0

आप इसे इस तरह परिभाषित कर सकते हैं:

class Foo {
  static MyConst = 200;

  myFunc() {
    const doubleConst = Foo.MyConst * 2;
  }
}

0

आप import * asवाक्यविन्यास का उपयोग कर सकते हैं । हालांकि एक वर्ग नहीं, वे असली हैंconst चर हैं।

Constants.js

export const factor = 3;
export const pi = 3.141592;

index.js

import * as Constants from 'Constants.js'
console.log( Constants.factor );
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.