मैं ES6 वर्ग में "सार्वजनिक स्थैतिक क्षेत्र" कैसे बनाऊं?


86

मैं एक जावास्क्रिप्ट क्लास बना रहा हूं और मैं जावा में एक पब्लिक स्टेटिक फील्ड रखना चाहता हूं। यह प्रासंगिक कोड है:

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

यह मुझे मिलने वाली त्रुटि है:

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

ऐसा लगता है कि ES6 मॉड्यूल इसकी अनुमति नहीं देता है। क्या वांछित व्यवहार प्राप्त करने का कोई तरीका है या क्या मुझे एक गेटर लिखना है?


आप कौन से ECMAScript 6 इंजन कार्यान्वयन का उपयोग कर रहे हैं?
दाई

जवाबों:


136

आप एक्सेसर और "स्टैटिक" कीवर्ड का उपयोग करके "सार्वजनिक स्थैतिक क्षेत्र" बनाते हैं:

class Agent {
    static get CIRCLE() {
      return 1;
    }
    static get SQUARE() {
      return 2;
    }
}

Agent.CIRCLE; // 1

एक कल्पना को देखते हुए, 14.5 - कक्षा की परिभाषाएँ - आपको कुछ संदिग्ध रूप से प्रासंगिक दिखाई देगा :)

वर्गीकरण [यील्ड]:
  मेथडिफाइनमेंट [? यील्ड]
  स्टेटिक मेथडिफाइनमेंट [? यील्ड];

तो वहाँ से आप 14.5.14 तक का पालन कर सकते हैं - रनटाइम सेमेंटिक्स: क्लासडिफाइनमेंट एवल्यूशन - डबल चेक करने के लिए कि क्या यह वास्तव में ऐसा करता है जैसा दिखता है। विशेष रूप से, चरण 20:

  1. विधियों से क्रम में प्रत्येक ClassElement मी के लिए
    1. यदि IsStatic of m गलत है , तो
      1. स्थिति प्रोटेस्टफाइनिशन एवेलेशन के लिए एम के लिए तर्कों प्रोटो और झूठ के साथ प्रदर्शन करने का परिणाम हो।
    2. अन्य,
      1. स्थिति F और असत्य के साथ m के लिए PropertyDefinitionEvaluation करने का परिणाम है।
    3. यदि स्थिति अचानक पूर्ण हो जाती है, तो
      1. चल निष्पादन निष्पादन संदर्भ को lex करने के लिए LexicalEnvironment सेट करें।
      2. वापसी की स्थिति।

IsStatic में पहले परिभाषित किया गया है 14.5.9

ClassElement: स्टैटिक मेथडिफिनिशन
रिटर्न सही।

तो PropertyMethodDefinitionएक तर्क के रूप में "एफ" (निर्माता, फ़ंक्शन ऑब्जेक्ट) के साथ कहा जाता है, जो इसके बदले में उस ऑब्जेक्ट पर एक एक्सेसर विधि बनाता है

यह पहले से ही कम से कम IETP (तकनीकी पूर्वावलोकन), साथ ही 6to5 और ट्रेसेर कंपाइलर में काम करता है।


किसी और को देखने के लिए, स्थिर एक्सेसर गुण नोड में अभी तक समर्थित नहीं हैं। : - / kangax.github.io/compat-table/es6/…
डेविड हर्नान्डेज

1
कम से कम Node.js 6.x + के रूप में, यह समर्थित है।
NuSkooler

ध्यान दें कि यदि आप प्रवाह का उपयोग कर रहे हैं, तो आपको unsafe.enable_getters_and_setters=trueअपने .flowconfig के नीचे एक लाइन जोड़ना होगा [options](जो कष्टप्रद है)।
क्रिस्टीना

यह मेरे लिए काम नहीं करेगा मैं `` अनहेल्ड रिजेक्शन टाइप हो रहा हूँ टाइप करें: क्लास कलेक्शन का संपत्ति डेटा सेट नहीं कर सकता है {api_1 | स्थिर हो जाओ dataHashKey () {api_1 | वापसी 'संग्रह'; एपि १ | } `` `
पावन

54

डैनियल एरेनबर्ग और जेफ मॉरिसन द्वारा "स्टेटिक क्लास फीचर्स" नामक एक स्टेज 3 ECMAScript प्रस्ताव है जिसका उद्देश्य इस समस्या को हल करना है। स्टेज 3 "क्लास फील्ड्स" प्रस्ताव के साथ, भविष्य का कोड इस तरह दिखेगा:

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;

बैबल @ बैबल / प्लगइन-प्रपोजल-क्लास-प्रॉपर्टीज़ ( स्टेज -3 प्रीसेट में शामिल ) के माध्यम से क्लास फील्ड ट्रांसप्लान्टिंग का समर्थन करता है , ताकि आप अपने जावास्क्रिप्ट रनटाइम का समर्थन न करने पर भी इस सुविधा का उपयोग कर सकें।


@ Kangax के एक गॉटर घोषित करने के समाधान की तुलना में, यह समाधान अधिक प्रदर्शनशील भी हो सकता है, क्योंकि यहां संपत्ति को फ़ंक्शन के माध्यम से कॉल करने के बजाय सीधे एक्सेस किया जाता है।

यदि यह प्रस्ताव स्वीकार हो जाता है, तो यह जावास्क्रिप्ट कोड को इस तरह से लिखना संभव होगा, जो जावा और C Java जैसी पारंपरिक ऑब्जेक्ट-ओरिएंटेड भाषाओं के समान है।


संपादित करें : एक एकीकृत वर्ग फ़ील्ड प्रस्ताव अब चरण 3 पर है; बाबेल v7.x संकुल को अद्यतन करें।

संपादित करें (फरवरी 2020) : स्थिर वर्ग सुविधाओं को एक अलग प्रस्ताव में विभाजित किया गया है। धन्यवाद @ GOTO0!


मुझे लगता है कि प्रासंगिक प्रस्ताव वास्तव में यह एक है ( स्टेटिक क्लास फीचर्स )।
गोटो 0

29

ECMAScript 6 (फरवरी 2015 तक) के वर्तमान ड्राफ्ट में, सभी वर्ग गुणों के तरीके होने चाहिए, न कि मान (ECMAScript में एक "गुण" एक ओओपी क्षेत्र में अवधारणा के समान है, सिवाय इसके कि फ़ील्ड वैल्यू एक Functionऑब्जेक्ट होनी चाहिए , किसी भी नहीं अन्य मान जैसे कि Numberया Object)।

आप अभी भी पारंपरिक ECMAScript कंस्ट्रक्टर प्रॉपर्टी स्पेसर्स का उपयोग करके इन्हें निर्दिष्ट कर सकते हैं:

 class Agent {
 }
 Agent.CIRCLE = 1;
 Agent.SQUARE = 2;
 ...

11
ध्यान दें कि ES6 classसिंटैक्स पारंपरिक जेएस कंस्ट्रक्टर कार्यों और प्रोटोटाइप के लिए वैसे भी सिंटैक्टिक चीनी है।
मैट ब्राउन ने

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

@ मुझे पता चला कि ओपी संदर्भ के लिए स्थिरांक को स्टोर करने की कोशिश कर रहा है (लगभग एक सी # / नेट की तरह enum)।
दाई

2
@MattBrowne हाँ, लेकिन स्पष्ट classवाक्यविन्यास होने के लिए कुछ निश्चित अंतर भी हैं। उदाहरण के लिए, एक विधि के साथ घोषित किया Class.prototype.method = function () {};जा सकने योग्य है (फॉर-इन लूप के साथ दिखाई देता है), जबकि classविधियां गणना योग्य नहीं हैं।
टिमोथी गु

4

स्थिर चर का पूरा लाभ पाने के लिए मैंने इस दृष्टिकोण का पालन किया। अधिक विशिष्ट होने के लिए, हम इसका उपयोग निजी चर का उपयोग करने के लिए कर सकते हैं या केवल सार्वजनिक गेटटर, या गेटटर या सेटर दोनों होने के लिए कर सकते हैं। पिछले मामले में यह ऊपर दिए गए समाधान में से एक के समान है।

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'];

मैं एक और क्लास बढ़ा सकता हूं, जो उरल का विस्तार है और इसने काम किया।

मैंने अपने ES6 कोड को ES5 में बदलने के लिए बैबल का उपयोग किया


1
"पूर्ण लाभ" क्या है? नहीं चाहेंगे class Url { static getQueries… }; Url.staticMember = [];बहुत सरल किया गया है?
बेर्गी जूल

वे ===दोनों उपज की तुलना करते हैं false, btw
बर्गी

"पूर्ण लाभ" का अर्थ है, उपरोक्त तरीके से आप _staticMember को निजी रख सकते हैं, यदि आप चाहें।
एसएम अदनान

-1

@ भाषा का जवाब पारंपरिक OOP भाषा के संपूर्ण स्थैतिक व्यवहार की नकल नहीं करता है, क्योंकि आप स्थिर संपत्ति तक पहुँच नहीं सकते हैं जैसे कि यह const agent = new Agent; agent.CIRCLE; // Undefined

यदि आप ओओपी की तरह स्थिर संपत्ति का उपयोग करना चाहते हैं, तो यहां मेरा समाधान है:

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


1
staticउदाहरण के लिए किसी क्षेत्र पर पहुँचना असामान्य होगा, जो आप नहीं कहेंगे? कुछ भाषाओं में, जैसे कि जावा, आईडीई वास्तव में एक चेतावनी / संकेत जारी करता है यदि आप ऐसा कुछ करते हैं।
Isac

@ आईसैक हाँ आप सही हैं। उदाहरण के लिए पहुँच हतोत्साहित है और इसलिए मेरा जवाब है। समाधान का सिर्फ एक और परिप्रेक्ष्य। 😀
legend80s
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.