चूंकि आपने similar question से पूछा है, चलिए इसे चरण-दर-चरण लेते हैं। यह थोड़ा लंबा है, लेकिन यह आपको लिखने पर खर्च करने से कहीं अधिक समय बचा सकता है:
संपत्ति क्लाइंट कोड के स्वच्छ अलगाव के लिए डिज़ाइन की गई एक ओओपी सुविधा है। उदाहरण के लिए, कुछ ई-दुकान में आप इस तरह की वस्तुओं हो सकता है:
function Product(name,price) {
this.name = name;
this.price = price;
this.discount = 0;
}
var sneakers = new Product("Sneakers",20); // {name:"Sneakers",price:20,discount:0}
var tshirt = new Product("T-shirt",10); // {name:"T-shirt",price:10,discount:0}
फिर अपने ग्राहक कोड (ई-शॉप), आप अपने उत्पादों के लिए छूट जोड़ सकते हैं में
:
function badProduct(obj) { obj.discount+= 20; ... }
function generalDiscount(obj) { obj.discount+= 10; ... }
function distributorDiscount(obj) { obj.discount+= 15; ... }
बाद में , ई-दुकान के मालिक को यह महसूस हो सकता है कि छूट 80% से अधिक नहीं हो सकती है। अब आप, तो ई-दुकान के मालिक आगे, अपनी रणनीति बदल सकते हैं की तरह "अगर ग्राहक पुनर्विक्रेता है ग्राहक कोड में छूट संशोधन के हर घटना खोजने के लिए और एक लाइन
if(obj.discount>80) obj.discount = 80;
जोड़ने की जरूरत है अधिक से अधिक छूट 90% " हो सकता है। और आपको फिर से कई स्थानों पर परिवर्तन करने की आवश्यकता है और साथ ही आपको रणनीतियों को बदलने के लिए इन पंक्तियों को बदलने के लिए याद रखना होगा। यह एक खराब डिजाइन है। यही कारण है कि encapsulation ओओपी का मूल सिद्धांत है।अगर निर्माता इस तरह था:
function Product(name,price) {
var _name=name, _price=price, _discount=0;
this.getName = function() { return _name; }
this.setName = function(value) { _name = value; }
this.getPrice = function() { return _price; }
this.setPrice = function(value) { _price = value; }
this.getDiscount = function() { return _discount; }
this.setDiscount = function(value) { _discount = value; }
}
तो फिर तुम सिर्फ getDiscount
(एक्सेसर) और setDiscount
(mutator) तरीके बदल सकते हैं। समस्या यह है कि अधिकांश सदस्य सामान्य चर की तरह व्यवहार करते हैं, केवल छूट को विशेष देखभाल की आवश्यकता होती है। लेकिन अच्छे डिज़ाइन को कोड को विस्तारित रखने के लिए प्रत्येक डेटा सदस्य के encapsulation की आवश्यकता होती है। तो आपको बहुत सारे कोड जोड़ने की ज़रूरत है जो कुछ भी नहीं करता है। यह भी एक खराब डिजाइन है, बॉयलरप्लेट एंटीपाटरर्न। कभी-कभी आप फ़ील्ड को बाद में तरीकों से दोबारा नहीं कर सकते हैं (eshop कोड बड़ा हो सकता है या कुछ तृतीय-पक्ष कोड पुराने संस्करण पर निर्भर हो सकता है), इसलिए बॉयलरप्लेट यहां कम बुराई है। लेकिन फिर भी, यह बुराई है। यही कारण है कि कई भाषाओं में गुण पेश किए गए थे। आप मूल कोड रख सकता है, बस get
और set
ब्लॉक के साथ एक संपत्ति में छूट सदस्य परिणत: (सही छूट मूल्य के लिए जिम्मेदारी ग्राहक कोड से ले जाया गया था ई:
function Product(name,price) {
this.name = name;
this.price = price;
//this.discount = 0; // <- remove this line and refactor with the code below
var _discount; // private member
Object.defineProperty(this,"discount",{
get: function() { return _discount; },
set: function(value) { _discount = value; if(_discount>80) _discount = 80; }
});
}
// the client code
var sneakers = new Product("Sneakers",20);
sneakers.discount = 50; // 50, setter is called
sneakers.discount+= 20; // 70, setter is called
sneakers.discount+= 20; // 80, not 90!
alert(sneakers.discount); // getter is called
नोट पिछले लेकिन एक लाइन दुकान परिभाषा) उत्पाद परिभाषा के लिए। उत्पाद अपने डेटा सदस्यों को सुसंगत रखने के लिए ज़िम्मेदार है। अच्छा डिजाइन (लगभग कहा जाता है) अगर कोड हमारे विचारों के समान काम करता है।
गुणों के बारे में बहुत कुछ।
सी # में, गुण में खेतों बदलने ताकि सार्वजनिक क्षेत्रों Auto-Implemented Properties के रूप में कोडित किया जाना चाहिए अपने कोड में इस्तेमाल किया जा सकता है, तो एक breaking change है,: लेकिन जावास्क्रिप्ट सी # की तरह शुद्ध वस्तु उन्मुख भाषाओं और कोड अलग तरह से सुविधाओं से अलग है अलग संकलित ग्राहक।
जावास्क्रिप्ट में, मानक गुण (साथ गेटर और सेटर ऊपर वर्णित डेटा सदस्य) एक्सेसर वर्णनकर्ता (लिंक आप अपने प्रश्न में है में) द्वारा परिभाषित कर रहे हैं। विशेष रूप से, आप डेटा डिस्क्रिप्टर का उपयोग कर सकते हैं (इसलिए आप i.e का उपयोग नहीं कर सकते हैं।मूल्य और एक ही संपत्ति पर) सेट:
- एक्सेसर वर्णनकर्ता = get + सेट (उदाहरण के ऊपर देखें)
- प्राप्त एक समारोह होना चाहिए; इसका रिटर्न वैल्यू संपत्ति पढ़ने में उपयोग किया जाता है; यदि निर्दिष्ट नहीं है, डिफ़ॉल्ट अपरिभाषित है, जो एक समारोह है कि अपरिभाषित
- सेट एक समारोह होना चाहिए देता है की तरह बर्ताव करता है, इसका पैरामीटर संपत्ति के मूल्य को आवंटित करने में आरएचएस से भरा है; यदि निर्दिष्ट नहीं है, डिफ़ॉल्ट अपरिभाषित है, जो एक खाली समारोह
- डेटा वर्णनकर्ता = मूल्य + लिखने योग्य (नीचे उदाहरण देखें)
- मूल्य डिफ़ॉल्ट की तरह बर्ताव करता अपरिभाषित है; यदि लिखने योग्य, विन्यास और गणनीय (नीचे देखें) सही हैं, संपत्ति एक साधारण डेटा फ़ील्ड
- लिखने योग्य तरह बर्ताव करता है - डिफ़ॉल्ट झूठी; यदि सही नहीं है, तो संपत्ति केवल पढ़ी जाती है; लिखने का प्रयास त्रुटि के बिना अनदेखा किया गया है *!
दोनों वर्णनकर्ता इन सदस्यों हो सकता है:
- विन्यास - डिफ़ॉल्ट झूठी; यदि सही नहीं है, तो संपत्ति को हटाया नहीं जा सकता है; हटाने के प्रयास को त्रुटि के बिना अनदेखा किया जाता है *!
- गणनीय - डिफ़ॉल्ट झूठी; यदि सही है, तो इसे
for(var i in theObject)
में पुनरावृत्त किया जाएगा; झूठे हैं, तो यह दोहराया नहीं किया जाएगा, लेकिन यह अभी भी सार्वजनिक रूप से सुलभ है
* जब तक strict mode में - उस मामले में जे एस बंद हो जाता है लेखन त्रुटि के साथ निष्पादन जब तक यह try-catch block
में फंस जाता है इन पढ़ने के लिए सेटिंग्स, Object.getOwnPropertyDescriptor()
का उपयोग करें।
उदाहरण से जानें:
- Object.preventExtensions(yourObject) रोकता है:
var o = {};
Object.defineProperty(o,"test",{
value: "a",
configurable: true
});
console.log(Object.getOwnPropertyDescriptor(o,"test")); // check the settings
for(var i in o) console.log(o[i]); // nothing, o.test is not enumerable
console.log(o.test); // "a"
o.test = "b"; // o.test is still "a", (is not writable, no error)
delete(o.test); // bye bye, o.test (was configurable)
o.test = "b"; // o.test is "b"
for(var i in o) console.log(o[i]); // "b", default fields are enumerable
आप ग्राहक कोड इस तरह धोखा अनुमति देने के लिए नहीं करना चाहते हैं, तो आप कारावास के तीन स्तरों से वस्तु सीमित कर सकते हैं नई गुण में जोड़ा जाएगा yourObject। ऑब्जेक्ट पर विधि का उपयोग किया गया था या नहीं, यह जांचने के लिए Object.isExtensible(<yourObject>)
का उपयोग करें। रोकथाम उथले (नीचे पढ़ें) है।
- Object.seal(yourObject) ऊपर जैसा ही है और गुणों को हटाया नहीं जा सकता है (प्रभावी रूप से सभी गुणों के लिए
configurable: false
सेट करता है)। ऑब्जेक्ट पर इस सुविधा का पता लगाने के लिए Object.isSealed(<yourObject>)
का उपयोग करें। मुहर उथले (नीचे पढ़ें) है।
- Object.freeze(yourObject) ऊपर जैसा ही है और गुणों को बदला नहीं जा सकता है (प्रभावी रूप से
writable: false
डेटा डिस्क्रिप्टर के साथ सभी गुणों को सेट करता है)। सेटर की लिखने योग्य संपत्ति प्रभावित नहीं होती है (क्योंकि इसमें कोई नहीं है)। फ्रीज उथले: इसका मतलब है कि यदि संपत्ति ऑब्जेक्ट है, तो इसकी गुण जमे हुए नहीं हैं (यदि आप चाहें, तो आपको deep copy - cloning के समान "गहरी फ्रीज" जैसी कुछ करना चाहिए)। इसका पता लगाने के लिए Object.isFrozen(<yourObject>)
का उपयोग करें।
यदि आप केवल कुछ पंक्तियों को मजा लिखते हैं तो आपको इससे परेशान करने की आवश्यकता नहीं है। लेकिन अगर आप एक गेम को कोड करना चाहते हैं (जैसा कि आपने लिंक किए गए प्रश्न में उल्लेख किया है), आपको वास्तव में अच्छी डिजाइन की परवाह करनी चाहिए। एंटीपाटरर्न और कोड गंध के बारे में कुछ करने का प्रयास करें। यह आपको जैसी स्थितियों से बचने में मदद करेगा "ओह, मुझे फिर से अपना कोड फिर से लिखना होगा!", यदि आप बहुत कुछ कोड करना चाहते हैं तो यह आपको निराशा के महीने बचा सकता है। सौभाग्य।
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty यह एक उत्कृष्ट ट्यूटोरियल यहाँ है। – Martian2049