प्रॉपर्टी डिस्क्रिप्टर

ऑब्जेक्ट प्रॉपर्टी के साथ आपका ज़्यादातर इंटरैक्शन, शायद सतह-लेवल पर होगा. इसमें, ऑब्जेक्ट लिटरल बनाना और कुंजियों का इस्तेमाल करके प्रॉपर्टी वैल्यू को सेट करना और ऐक्सेस करना शामिल है. हालांकि, किसी ऑब्जेक्ट की किसी भी प्रॉपर्टी को अंदरूनी तौर पर कॉन्फ़िगर किया जा सकता है, ताकि उन प्रॉपर्टी को ऐक्सेस करने, उनमें बदलाव करने, और उन्हें तय करने के तरीके पर बारीकी से कंट्रोल किया जा सके. हर ऑब्जेक्ट प्रॉपर्टी में, दिखाई न देने वाले एट्रिब्यूट का एक ऐसा सेट होता है जिसमें उस प्रॉपर्टी से जुड़ा मेटाडेटा होता है. इन्हें "प्रॉपर्टी डिस्क्रिप्टर" कहते हैं.

किसी भी प्रॉपर्टी से जुड़े दो तरह के डिस्क्रिप्टर होते हैं: डेटा डिस्क्रिप्टर और ऐक्सेसर डिस्क्रिप्टर. डेटा डिस्क्रिप्टर में, ऐसी कुंजी और वैल्यू के जोड़े शामिल होते हैं जिनमें प्रॉपर्टी की वैल्यू शामिल होती है. भले ही, वह वैल्यू लिखी जा सकने वाली, कॉन्फ़िगर की जा सकने वाली या गिनती के लायक हो. ऐक्सेसर डिस्क्रिप्टर में ऐसे फ़ंक्शन होते हैं जो किसी प्रॉपर्टी के सेट होने, बदलने या ऐक्सेस किए जाने पर काम करते हैं.

प्रॉपर्टी डिस्क्रिप्टर का टाइप
Object.defineProperty() से शुरू होने वाली डिफ़ॉल्ट वैल्यू
ब्यौरा
[[Value]] डेटा undefined इसमें प्रॉपर्टी की वैल्यू शामिल होती है.
[[Writable]] डेटा false इससे यह तय होता है कि प्रॉपर्टी की वैल्यू बदली जा सकती है या नहीं.
[[Get]] ऐक्सेसर undefined प्रॉपर्टी का getter फ़ंक्शन, जो प्रॉपर्टी को ऐक्सेस किए जाने पर काम करता है.
[[Set]] ऐक्सेसर undefined प्रॉपर्टी का setter फ़ंक्शन, यह तब काम करता है, जब प्रॉपर्टी को सेट किया जाता है या उसमें बदलाव किया जाता है.
[[Configurable]] दोनों false अगर यह false है, तो प्रॉपर्टी को मिटाया नहीं जा सकता और न ही इसके एट्रिब्यूट को बदला जा सकता है. अगर यह false है और [[Writable]], true है, तो प्रॉपर्टी की वैल्यू अब भी बदली जा सकती है.
[[Enumerable]] दोनों false अगर यह true है, तो for...in लूप या Object.keys() स्टैटिक तरीके का इस्तेमाल करके, प्रॉपर्टी में फिर से बदलाव किया जा सकता है.

इनमें से हर प्रॉपर्टी, [[Prototype]] के समान शॉर्टहैंड का इस्तेमाल करती है. इससे पता चलता है कि इन प्रॉपर्टी को सीधे ऐक्सेस करने के लिए नहीं बनाया गया है. इसके बजाय, किसी ऑब्जेक्ट की प्रॉपर्टी तय करने या उनमें बदलाव करने के लिए, Object.defineProperty() स्टैटिक तरीके का इस्तेमाल करें. Object.defineProperty() तीन आर्ग्युमेंट स्वीकार करता है: जिस प्रॉपर्टी पर कार्रवाई करनी है, वह प्रॉपर्टी कुंजी जिसे बनाना या बदलना है, और एक ऑब्जेक्ट, जिसमें बनाई जा रही प्रॉपर्टी से जुड़े जानकारी देने वाले(जानकारी देने वाले) हैं या बदलाव किए जा रहे हैं.

डिफ़ॉल्ट रूप से, Object.defineProperty() का इस्तेमाल करके बनाई गई प्रॉपर्टी लिखने लायक, गिनने लायक या कॉन्फ़िगर करने लायक नहीं होती हैं. हालांकि, ऑब्जेक्ट लिटरल के तौर पर या डॉट या ब्रैकेट नोटेशन का इस्तेमाल करके जो भी प्रॉपर्टी बनाई जाती है वह लिखी जा सकती है, उसकी गिनती की जा सकती है, और कॉन्फ़िगर की जा सकती है.

const myObj = {};

Object.defineProperty(myObj, 'myProperty', {
  value: true,
  writable: false
});

myObj.myProperty;
> true

myObj.myProperty = false;

myObj.myProperty;
> true

उदाहरण के लिए, जब [[Writable]] की वैल्यू false होती है, तो जुड़ी हुई प्रॉपर्टी के लिए नई वैल्यू सेट करने की कोशिश करने पर, सख्त मोड के बाहर यह कार्रवाई नहीं की जा सकती. साथ ही, स्ट्रिक्ट मोड में गड़बड़ी दिखती है:

{
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}
> true

(function () {
    "use strict";
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}());\
> Uncaught TypeError: "myProperty" is read-only

डिस्क्रिप्टर का सही तरीके से इस्तेमाल करना एक ऐडवांस कॉन्सेप्ट है, लेकिन ऑब्जेक्ट के साथ सामान्य तरीके से काम करने के लिए, ऑब्जेक्ट की अंदरूनी संरचना को समझना ज़रूरी है. उदाहरण के लिए, ये कॉन्सेप्ट तब लागू होते हैं, जब Object.create() स्टैटिक तरीके का इस्तेमाल किया जाता है. इससे आपको नए ऑब्जेक्ट से जुड़े किसी भी प्रोटोटाइप पर बेहतर कंट्रोल मिलता है.

Object.create() किसी मौजूदा ऑब्जेक्ट को उसके प्रोटोटाइप के तौर पर इस्तेमाल करके, एक नया ऑब्जेक्ट बनाता है. इससे नया ऑब्जेक्ट, किसी दूसरे उपयोगकर्ता के तय किए गए ऑब्जेक्ट की प्रॉपर्टी और तरीकों को उसी तरह इनहेरिट करता है जिस तरह ऑब्जेक्ट, JavaScript के पहले से मौजूद Object प्रोटोटाइप की प्रॉपर्टी और इनहेरिट करते हैं. जब किसी ऑब्जेक्ट को आर्ग्युमेंट के तौर पर Object.create() शुरू किया जाता है, तो यह पास किए गए ऑब्जेक्ट के साथ एक खाली ऑब्जेक्ट बनाता है. यह उसका प्रोटोटाइप है.

const myCustomPrototype = {
  'myInheritedProp': 10
};

const newObject = Object.create( myCustomPrototype );

newObject;
> Object {  }
<prototype>: Object { myInheritedProp: 10 }
  myInheritedProp: 10
  <prototype>: Object { … }

नए बनाए गए ऑब्जेक्ट के लिए अपनी प्रॉपर्टी तय करने के लिए, Object.create दूसरा तर्क ले सकता है. यह आर्ग्युमेंट Object.defineProperty() से मिलते-जुलते सिंटैक्स का इस्तेमाल करता है. इसका मतलब है कि डिस्क्रिप्टर एट्रिब्यूट के सेट के लिए ऑब्जेक्ट मैपिंग की:

const myCustomPrototype = {
  'myInheritedProp': 10
};

const myObj = Object.create( myCustomPrototype, {
        myProperty: {
            value: "The new property value.",
            writable: true,
            configurable: true
        }
  });

myObj;
> Object { … }
    myProperty: "The new property value."
    <prototype>: Object { myInheritedProp: 10 }

इस उदाहरण में, नया ऑब्जेक्ट (myObj) अपने प्रोटोटाइप के तौर पर लिटरल वैल्यू (myCustomPrototype) का इस्तेमाल करता है, जिसमें इनहेरिट किया गया Object.prototype शामिल होता है. इस वजह से, इनहेरिट किए गए प्रोटोटाइप की एक सीरीज़ बनती है, जिसे प्रोटोटाइप चेन कहते हैं. हर ऑब्जेक्ट का एक प्रोटोटाइप होता है, चाहे वह असाइन किया गया हो या इनहेरिट किया गया हो, जिसमें उसका खुद का एक असाइन किया गया या इनहेरिट किया गया प्रोटोटाइप होता है. यह चेन, null प्रोटोटाइप पर खत्म होती है, जिसका अपना कोई प्रोटोटाइप नहीं है.

const myPrototype = {
  'protoProp': 10
};

const newObject = Object.setPrototypeOf( { 'objProp' : true }, myPrototype );

newObject;
> Object { objProp: true }
    objProp: true
    <prototype>: Object { protoProp: 10 }
        protoProp: 10
        <prototype>: Object { … }

वैल्यू के प्रोटोटाइप में शामिल प्रॉपर्टी, किसी ऑब्जेक्ट के "टॉप लेवल" पर उपलब्ध होती हैं. इसके लिए, प्रोटोटाइप प्रॉपर्टी को सीधे ऐक्सेस करने की ज़रूरत नहीं होती:

const objectLiteral = {
    "value" : true
};

objectLiteral;
> Object { value: true }
    value: true
    <prototype>: Object { … }

objectLiteral.toString();
"[object Object]"

यह पैटर्न किसी ऑब्जेक्ट से जुड़ी पूरी प्रोटोटाइप चेन के लिए सही होता है: किसी प्रॉपर्टी को ऐक्सेस करने की कोशिश करते समय, अनुवादक उस प्रॉपर्टी को प्रोटोटाइप चेन के हर "लेवल" पर ऊपर से नीचे तक खोजता है, जब तक कि वह प्रॉपर्टी या चेन खत्म नहीं हो जाता:

const myCustomPrototype = {
  'protoProp': "Prototype property value."
};

const myObj = Object.create( myCustomPrototype, {
    myProperty: {
        value: "Top-level property value.",
        writable: true,
        configurable: true
    }
});

myObj.protoProp;
> "Prototype property value."

जांचें कि आपको कितना समझ आया

कौन से डिस्क्रिप्टर ऐक्सेसर हैं?

[[Get]]
[[Set]]
[[Writable]]