टाइपस्क्रिप्ट में सेट और प्राप्त करें


656

मैं एक संपत्ति के लिए विधि बनाने और सेट करने की कोशिश कर रहा हूं:

private _name: string;

Name() {
    get:
    {
        return this._name;
    }
    set:
    {
        this._name = ???;
    }
}

मान सेट करने के लिए कीवर्ड क्या है?


12
अंडरस्कोर और पास्कलकेस टाइपस्क्रिप्ट कोडिंग गाइडलाइन्स के साथ संघर्ष करता है: github.com/Microsoft/TypeScript/wiki/Coding-guidelines
Niels Steenbeek

2
Hi @NielsSteenbeek - गुण और बैकिंग फ़ील्ड के साथ टाइपस्क्रिप्ट योगदानकर्ताओं के दिशानिर्देशों का पालन करते हुए आप एक नाम संघर्ष के साथ समाप्त होंगे। सुझाया दृष्टिकोण क्या है?
जॉर्डन

शायद: typescript private name: string; getName() { get: { return this.name; } set: { this.name = ???; } }
जॉर्डन

7
अच्छी बात यह है कि टाइपस्क्रिप्ट कोडिंग दिशा-निर्देश बहुत बदसूरत हैं। मैं उन्हें केवल जबरदस्ती के तहत इस्तेमाल करूंगा (जैसे मुझे ऐसा करने के लिए भुगतान किया गया था)।
थॉमस एडिंग

14
@NielsSteenbeek: क्या आपने वह दस्तावेज़ पढ़ा है? "यह टाइपस्क्रिप्ट समुदाय के लिए एक निर्धारित गाइडलाइन नहीं है"
जोनाथन कास्ट

जवाबों:


1081

टाइपस्क्रिप्ट, एक्शनस्क्रिप्ट 3 की तरह गेटटर / सेटर सिंटैक्स का उपयोग करता है।

class foo {
    private _bar: boolean = false;
    get bar(): boolean {
        return this._bar;
    }
    set bar(value: boolean) {
        this._bar = value;
    }
}

ECMAScript 5 Object.defineProperty()सुविधा का उपयोग करके यह जावास्क्रिप्ट का उत्पादन करेगा ।

var foo = (function () {
    function foo() {
        this._bar = false;
    }
    Object.defineProperty(foo.prototype, "bar", {
        get: function () {
            return this._bar;
        },
        set: function (value) {
            this._bar = value;
        },
        enumerable: true,
        configurable: true
    });
    return foo;
})();

तो इसका उपयोग करने के लिए,

var myFoo = new foo();
if(myFoo.bar) {         // calls the getter
    myFoo.bar = false;  // calls the setter and passes false
}

हालाँकि, इसका उपयोग करने के लिए, आपको यह सुनिश्चित करना होगा कि टाइपस्क्रिप्ट कंपाइलर ECMAScript5 को लक्षित करे। यदि आप कमांड लाइन संकलक चला रहे हैं, तो --targetइस तरह ध्वज का उपयोग करें;

tsc --target ES5

यदि आप Visual Studio का उपयोग कर रहे हैं, तो आपको TypeScriptCompile बिल्ड टूल के लिए फ़्लैग को कॉन्फ़िगरेशन में जोड़ने के लिए अपनी प्रोजेक्ट फ़ाइल को संपादित करना होगा। आप यहाँ देख सकते हैं कि :

जैसा कि @DanFromGermany नीचे सुझाता है, अगर आपका बस एक स्थानीय संपत्ति को पढ़ना और लिखना है foo.bar = true, तो एक सेटर और गेट्टर जोड़ी का ओवरकिल होना। आप हमेशा उन्हें बाद में जोड़ सकते हैं यदि आपको कुछ करने की ज़रूरत है, जैसे लॉगिंग, जब भी संपत्ति पढ़ी या लिखी जाती है।


59
अच्छा उत्तर। इसके अलावा, ध्यान दें कि, C # के विपरीत, गुण वर्तमान में टाइपस्क्रिप्ट (v0.9.5) में वर्चुअलाइज्ड नहीं हैं। जब आप एक व्युत्पन्न वर्ग में "गेट बार ()" को लागू करते हैं, तो आप माता-पिता में "बार ()" की जगह ले रहे हैं। निहितार्थों में बेस क्लास एक्सेसर को व्युत्पन्न एक्सेसर से कॉल करने में सक्षम नहीं होना शामिल है। यह केवल गुणों के लिए सही है - विधियां व्यवहार करती हैं जैसा कि आप उम्मीद कर सकते हैं। स्टीवफेंटन का जवाब यहां देखें: stackoverflow.com/questions/13121431/…
डेविड क्यूकेया

14
मैं अंडरस्कोर के बारे में थोड़ा उलझन में हूं। टाइपस्क्रिप्ट अधिवेशन में कहा गया है कि निजी चरों के लिए अंडरस्कोर का इस्तेमाल न करें? लेकिन इस मामले में, हमें अंडरस्कोर का उपयोग करना होगा - या हम निजी और सार्वजनिक "बार" के बीच संघर्ष करेंगे
कोकोडोको

4
अंडरस्कोर का उपयोग निजी गुणों के लिए एक व्यक्तिगत प्राथमिकता है। हालाँकि, मेरा मानना ​​है कि आप सही हैं कि हम चाहते हैं कि संपत्ति का गेट्टर / सेटर के तरीकों से अलग नाम हो।
एज़वर्ड

3
क्यों प्रयोग करते हैं myFoo.bar = trueके बजाय myFoo.bar(true);या myFoo.setBar(true);??
डैनियल डब्ल्यू।

6
@DanFromGermany "गेट" और "सेट" विधियों की एक जोड़ी के लिए एक संपत्ति "सिंटैक्टिक शुगर" है। Microsoft ने Visual Basic के साथ एक संपत्ति की अवधारणा की उत्पत्ति की और इसे .NET भाषाओं जैसे C # और VB.NET पर ले गया। उदाहरण के लिए, गुण देखें (C # प्रोग्रामिंग गाइड) । गुण किसी वस्तु की स्थिति तक पहुँचने को सरल बनाते हैं और (मेरी राय में) "प्राप्त / सेट" विधि जोड़े से निपटने के लिए होने की "नीचता" को समाप्त करते हैं। (या कभी-कभी केवल "प्राप्त करें" विधियां जहां अपरिवर्तनीयता वांछित है।)
डेविड आरआर

112

एज़वर्ड ने पहले से ही एक अच्छा जवाब दिया है, लेकिन मैंने देखा कि टिप्पणियों में से एक पूछता है कि इसका उपयोग कैसे किया जाता है। मेरे जैसे लोगों के लिए जो इस प्रश्न पर ठोकर खाते हैं, मैंने सोचा कि यह गेटवे पर आधिकारिक दस्तावेज़ों के लिंक और टाइपस्क्रिप्ट वेबसाइट पर बसने के लिए उपयोगी होगा, क्योंकि यह अच्छी तरह से समझाता है, उम्मीद है कि हमेशा बदलाव के रूप में अद्यतित रहेंगे। बनाया और उदाहरण उपयोग दिखाता है:

http://www.typescriptlang.org/docs/handbook/classes.html

विशेष रूप से, उन लोगों के लिए जो इससे परिचित नहीं हैं, ध्यान दें कि आप एक कॉल करने वाले (और इसी तरह बसने वालों के लिए) में 'get' शब्द को शामिल नहीं करते हैं:

var myBar = myFoo.getBar(); // wrong    
var myBar = myFoo.get('bar');  // wrong

आपको बस यह करना चाहिए:

var myBar = myFoo.bar;  // correct (get)
myFoo.bar = true;  // correct (set) (false is correct too obviously!)

जैसे एक वर्ग दिया:

class foo {
  private _bar:boolean = false;

  get bar():boolean {
    return this._bar;
  }
  set bar(theBar:boolean) {
    this._bar = theBar;
  }
}

फिर निजी '_bar' संपत्ति के लिए 'बार' पाने वाले को बुलाया जाएगा।


अगर मैं एक सार्वजनिक वर्ग-स्तरीय संस्करण को एक संपत्ति के साथ बदलना चाहता था, तो क्या यह एक सीधा ड्रॉप-इन प्रतिस्थापन है जिसे मैं डाल सकता हूं और इसके बारे में चिंता नहीं कर सकता हूं? दूसरे शब्दों में, अगर मैं एक एक्सेसर और एक सेटर का परीक्षण करता हूं, तो क्या मैं इसे सफल बना सकता हूं? या ऐसे मामले हैं जहां यह बिल्कुल वैर के समान काम नहीं करेगा और मुझे उन सभी 100 स्थानों का परीक्षण करने की आवश्यकता है जो इस संस्करण / प्रोप का उपयोग करते हैं?
एडम प्लोचर

मुझे आश्चर्य हो रहा था कि क्या संपत्ति के नाम को गेट्टर या सेटर के तरीकों से अलग करने के लिए अंडरस्कोर का उपयोग करने के लिए वर्कअराउंड किया गया था। एक कोर्स में मैं कह रहा था कि वे अंडरस्कोर पसंद नहीं थे, लेकिन एक विकल्प नहीं दिया।
चाम

1
@cham आपको यहां अंडरस्कोर का उपयोग नहीं करना है ... यदि आप चाहें तो आप निजी चर नोटबार को कॉल कर सकते हैं।
रॉबर्ट मैककी

58

यहां एक कार्यशील उदाहरण दिया गया है जो आपको सही दिशा में इंगित करना चाहिए:

class Foo {
    _name;

    get Name() {
        return this._name;
    }

    set Name(val) {
        this._name = val;
    }
}

जावास्क्रिप्ट में गेटर्स और सेटर सिर्फ सामान्य कार्य हैं। सेटर एक फ़ंक्शन है जो एक पैरामीटर लेता है जिसका मूल्य सेट किया जा रहा मूल्य है।


30
स्पष्ट होने के लिए, संपत्ति, गेट्टर और सेटर होने की कोई आवश्यकता नहीं है static
ड्रू नोक

1
चर संदर्भ अभी भी स्थिर हैं। Foo._nameसाथ प्रतिस्थापित किया जाना चाहिएthis._name
जोहानिस

6

आप यह लिख सकते हैं

class Human {
    private firstName : string;
    private lastName : string;

    constructor (
        public FirstName?:string, 
        public LastName?:string) {

    }

    get FirstName() : string {
        console.log("Get FirstName : ", this.firstName);
        return this.firstName;
    }
    set FirstName(value : string) {
        console.log("Set FirstName : ", value);
        this.firstName = value;
    } 

    get LastName() : string {
        console.log("Get LastName : ", this.lastName);
        return this.lastName;
    }
    set LastName(value : string) {
        console.log("Set LastName : ", value);
        this.lastName = value;
    } 

}

2
कंस्ट्रक्टर में जनता क्यों?
मुरीलोकेन

17
हां, इस कोड में कंस्ट्रक्टर में सार्वजनिक नहीं किया जा सकता है। publicयहाँ नकली सदस्यों को परिभाषित करता है।
15

2
आप इसे लिख सकते हैं लेकिन यह अभ्यस्त नहीं
जस्टिन

3

TS ऑफरर्स और सेटर प्रदान करता है जो ऑब्जेक्ट प्रॉपर्टी को ऑब्जेक्ट के बाहर एक्सेस (गेट्टर) या अपडेटेड (सेटर) होने का अधिक नियंत्रण रखने की अनुमति देता है । प्रॉपर्टी को सीधे एक्सेस या अपडेट करने के बजाय प्रॉक्सी फ़ंक्शन कहा जाता है।

उदाहरण:

class Person {
    constructor(name: string) {
        this._name = name;
    }

    private _name: string;

    get name() {
        return this._name;
    }

    // first checks the length of the name and then updates the name.
    set name(name: string) {
        if (name.length > 10) {
            throw new Error("Name has a max length of 10");
        }

        this._name = name;  
    }

    doStuff () {
        this._name = 'foofooooooofoooo';
    }


}

const person = new Person('Willem');

// doesn't throw error, setter function not called within the object method when this._name is changed
person.doStuff();  

// throws error because setter is called and name is longer than 10 characters
person.name = 'barbarbarbarbarbar';  

1

यह सामान्य विधियों को बनाने के लिए बहुत समान है, बस कीवर्ड को आरक्षित getया setशुरुआत में रखें।

class Name{
    private _name: string;

    getMethod(): string{
        return this._name;
    }

    setMethod(value: string){
        this._name = value
    }

    get getMethod1(): string{
        return this._name;
    }

    set setMethod1(value: string){
        this._name = value
    }
}

class HelloWorld {

    public static main(){

        let test = new Name();

        test.setMethod('test.getMethod() --- need ()');
            console.log(test.getMethod());

        test.setMethod1 = 'test.getMethod1 --- no need (), and used = for set ';
            console.log(test.getMethod1);
    }
}
HelloWorld.main();

इस स्थिति में आप वापसी प्रकार को छोड़ सकते हैं get getMethod1() {

    get getMethod1() {
        return this._name;
    }

1

मुझे लगता है कि मुझे शायद ऐसा क्यों लगता है। आपके उदाहरण में, हम इसके लिए गेटर्स और सेटर चाहते थे _name। लेकिन हम एक असंबंधित वर्ग चर के लिए गेटर्स और सेटर्स बनाकर हासिल करते हैं Name

इस पर विचार करो:

class Car{
    private tiresCount = 4;
    get yourCarTiresCount(){
        return this.tiresCount ;
    }
    set yourCarTiresCount(count) {
        alert('You shouldn't change car tire count')
    }
}

उपरोक्त कोड निम्नलिखित है:

  1. getऔर (के लिए नहीं ) के setलिए गेटटर और सेटर बनाएं ।yourCarTiresCounttiresCount

पानेवाला है:

function() {
    return this.tiresCount ;
}

और सेटर है:

function(count) {
    alert('You shouldn't change car tire count');
}

मतलब, हर बार जब हम करते हैं new Car().yourCarTiresCount, गेट्टर रन होता है। और हर new Car().yourCarTiresCount('7')सेटर चलाता है।

  1. अप्रत्यक्ष रूप से निजी के लिए, गेट्टर नहीं बल्कि सेटर बनाएं tireCount

0

यदि आप किसी भी वस्तु पर प्राप्त करने और सेट करने के तरीके का उपयोग कर रहे हैं (कोई वर्ग नहीं) Proxy उपयोगी हो सकता है: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Object/Proxy

const target = {
  message1: "hello",
  message2: "everyone"
};

const handler3 = {
  get: function (target, prop, receiver) {
    if (prop === "message2") {
      return "world";
    }
    return Reflect.get(...arguments);
  },
};

const proxy3 = new Proxy(target, handler3);

console.log(proxy3.message1); // hello
console.log(proxy3.message2); // world

नोट: ध्यान रखें कि यह नया एपीआई समर्थित नहीं है और पुराने ब्राउज़रों के लिए आवश्यक पॉलीफिल है


-6

यदि आप टाइपस्क्रिप्ट मॉड्यूल के साथ काम कर रहे हैं और निर्यात किए जाने वाले एक गेटर को जोड़ने की कोशिश कर रहे हैं, तो आप कुछ इस तरह कर सकते हैं:

// dataStore.ts
export const myData: string = undefined;  // just for typing support
let _myData: string;  // for memoizing the getter results

Object.defineProperty(this, "myData", {
    get: (): string => {
        if (_myData === undefined) {
            _myData = "my data";  // pretend this took a long time
        }

        return _myData;
    },
});

फिर, आपके पास एक अन्य फ़ाइल में:

import * as dataStore from "./dataStore"
console.log(dataStore.myData); // "my data"

8
वह भयानक सलाह है। विशेष रूप से, thisकिसी मॉड्यूल के शीर्ष स्तर के दायरे में अपरिभाषित होना चाहिए। आप exportsइसके बजाय उपयोग कर सकते हैं, लेकिन आपको ऐसा बिल्कुल नहीं करना चाहिए क्योंकि यह व्यावहारिक रूप से संगतता समस्याओं का कारण बनता है
अलुआन हदाद
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.