अद्यतन २०१५:
जैसा कि ' वें उत्तर में बताया गया है , अब ईएस ६ (ईसीएमएस्क्रिप्ट २०१५) को अंतिम रूप दे दिया गया है, अधिक उपयुक्त दस्तावेज अब उपलब्ध है:
मूल उत्तर (ऐतिहासिक) समझ और अतिरिक्त उदाहरणों के लिए :
Reflection proposal
के लिए आगे बढ़ा दिया है ड्राफ्ट ECMAScript 6 विशिष्टता । यह दस्तावेज़ वर्तमान में Reflect
-object के तरीकों की रूपरेखा देता है और केवल -object के बारे में निम्नलिखित Reflect
बताता है:
रिफ्लेक्ट ऑब्जेक्ट एक साधारण वस्तु है।
[[प्रोटोटाइप]] रिफ्लेक्ट ऑब्जेक्ट का आंतरिक स्लॉट मानक निर्मित वस्तु प्रोटोटाइप ऑब्जेक्ट (१ ९ .१.३) है।
रिफ्लेक्ट ऑब्जेक्ट एक फ़ंक्शन ऑब्जेक्ट नहीं है। इसका [[निर्माण]] आंतरिक तरीका नहीं है; नए ऑपरेटर के साथ एक निर्माता के रूप में रिफ्लेक्ट ऑब्जेक्ट का उपयोग करना संभव नहीं है । रिफ्लेक्ट ऑब्जेक्ट में एक [[कॉल]] आंतरिक विधि भी नहीं होती है; फ़ंक्शन के रूप में रिफ्लेक्ट ऑब्जेक्ट को इनवोक करना संभव नहीं है।
हालांकि, ईएस हार्मनी में इसके उद्देश्य के बारे में एक संक्षिप्त व्याख्या है :
"@Reflect" मॉड्यूल कई उद्देश्यों को पूरा करता है:
- अब जब हमारे पास मॉड्यूल है, तो एक "@reflect" मॉड्यूल ऑब्जेक्ट पर पहले से परिभाषित कई प्रतिबिंब तरीकों के लिए एक अधिक प्राकृतिक स्थान है। बैकवर्ड-संगतता उद्देश्यों के लिए, यह संभावना नहीं है कि ऑब्जेक्ट पर स्थिर तरीके गायब हो जाएंगे। हालाँकि, नए तरीकों को ऑब्जेक्ट कंस्ट्रक्टर के बजाय "@reflect" मॉड्यूल में जोड़ा जाना चाहिए।
- प्रॉक्सी के लिए एक प्राकृतिक घर, वैश्विक प्रॉक्सी बाइंडिंग की आवश्यकता को टालता है।
- इस मॉड्यूल के अधिकांश तरीके प्रॉक्सी ट्रैप पर वन-टू-वन मैप करते हैं। प्रॉक्सी संचालकों को सुविधाजनक तरीके से संचालन के लिए इन विधियों की आवश्यकता होती है, जैसा कि नीचे दिखाया गया है।
तो, Reflect
ऑब्जेक्ट कई उपयोगिता फ़ंक्शंस प्रदान करता है, जिनमें से कई वैश्विक ऑब्जेक्ट पर परिभाषित ES5 विधियों के साथ ओवरलैप करने के लिए दिखाई देते हैं।
हालाँकि, यह वास्तव में स्पष्ट नहीं करता है कि मौजूदा समस्याएँ क्या हल करना चाहती हैं या क्या कार्यक्षमता जोड़ी जाती है। मुझे संदेह था कि यह शर्मनाक हो सकता है और वास्तव में, उपरोक्त सद्भाव-कल्पना लिंक 'इन तरीकों के गैर-मानक, अनुमानित कार्यान्वयन' के लिए हैं ।
उस कोड की जांच करना, इसके उपयोग के बारे में (आगे) विचार दे सकता है, लेकिन शुक्र है कि विकी भी है जो कई कारणों से रेखांकित करता है कि रिफ्लेक्ट ऑब्जेक्ट क्यों उपयोगी है :
(मैंने भविष्य के संदर्भ के लिए निम्न पाठ की प्रतिलिपि बनाई है (और स्वरूपित)। स्रोत के रूप में वे केवल उदाहरण हैं जो मुझे मिल सकते हैं। इसके अलावा, वे समझ में आते हैं, पहले से ही एक अच्छी व्याख्या है और प्रश्न के apply
उदाहरण को स्पर्श करें ।)
अधिक उपयोगी रिटर्न मान
कई ऑपरेशन Reflect
ES5 संचालन के समान हैं Object
, जैसे कि Reflect.getOwnPropertyDescriptor
और Reflect.defineProperty
। हालांकि, जब संपत्ति को सफलतापूर्वक परिभाषित किया गया था, तब तक Object.defineProperty(obj, name, desc)
या तो वापस आ जाएगा obj
, या TypeError
अन्यथा फेंक दें , Reflect.defineProperty(obj, name, desc)
केवल एक बूलियन वापस करने के लिए निर्दिष्ट किया जाता है जो इंगित करता है कि संपत्ति सफलतापूर्वक परिभाषित की गई थी या नहीं। यह आपको इस कोड को रिफलेक्टर करने की अनुमति देता है:
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
इसके लिए:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
अन्य तरीके जो ऐसी बूलियन सफलता की स्थिति लौटाते हैं Reflect.set
(एक संपत्ति को अद्यतन करने के लिए), Reflect.deleteProperty
(एक संपत्ति को हटाने के लिए), Reflect.preventExtensions
(एक वस्तु को गैर-एक्स्टेंसिबल बनाने के लिए) और Reflect.setPrototypeOf
(एक वस्तु के प्रोटोटाइप लिंक को अपडेट करने के लिए)।
प्रथम श्रेणी के संचालन
ईएस 5 में, यह पता लगाने का तरीका कि क्या एक वस्तु obj
को परिभाषित करना है या एक निश्चित संपत्ति का नाम लिखना है (name in obj)
। इसी तरह, एक संपत्ति को हटाने के लिए, एक का उपयोग करता है delete obj[name]
। जबकि समर्पित सिंटैक्स अच्छा और छोटा है, इसका मतलब यह भी है कि जब आप ऑपरेशन को प्रथम श्रेणी के मूल्य के रूप में पास करना चाहते हैं, तो आपको इन कार्यों को स्पष्ट रूप से लपेटना होगा।
इसके साथ Reflect
, इन कार्यों को आसानी से प्रथम श्रेणी के कार्यों के रूप में परिभाषित किया गया है:
Reflect.has(obj, name)
एक कार्यात्मक समतुल्य है (name in obj)
और Reflect.deleteProperty(obj, name)
एक ऐसा कार्य है जो जैसा करता हैdelete obj[name].
अधिक विश्वसनीय फ़ंक्शन अनुप्रयोग
ES5 में, जब कोई फ़ंक्शन f
को एक सरणी के रूप में पैक किए गए तर्कों की एक चर संख्या के साथ एक फ़ंक्शन को कॉल करना चाहता है args
और this
मान को बाध्य करता है obj
, तो एक व्यक्ति यह लिख सकता है:
f.apply(obj, args)
हालांकि, f
एक ऐसी वस्तु हो सकती है जो जानबूझकर या अनजाने में अपनी खुद की apply
विधि को परिभाषित करती है । जब आप वास्तव में यह सुनिश्चित करना चाहते हैं कि अंतर्निहित apply
फ़ंक्शन कहा जाता है, तो एक आम तौर पर लिखता है:
Function.prototype.apply.call(f, obj, args)
न केवल यह क्रिया है, यह जल्दी से समझना मुश्किल हो जाता है। साथ Reflect
, अब आप एक छोटा और आसान समझने के लिए रास्ते में एक विश्वसनीय समारोह कॉल कर सकते हैं:
Reflect.apply(f, obj, args)
परिवर्तनीय-तर्क निर्माता
कल्पना करें कि आप एक तर्क संख्या के साथ एक रचनाकार फ़ंक्शन को कॉल करना चाहते हैं। ईएस 6 में, नए प्रसार सिंटैक्स के लिए धन्यवाद, कोड लिखना संभव होगा:
var obj = new F(...args)
ईएस 5 में, यह लिखना कठिन है, क्योंकि एक फ़ंक्शन को केवल चर संख्या के तर्कों के साथ उपयोग F.apply
या F.call
कॉल कर सकता है, लेकिन F.construct
फ़ंक्शन के लिए new
चर संख्या के साथ कोई फ़ंक्शन नहीं है। साथ Reflect
, एक अब लिख सकते हैं, ES5 में:
var obj = Reflect.construct(F, args)
प्रॉक्सी जाल के लिए डिफ़ॉल्ट अग्रेषण व्यवहार
Proxy
मौजूदा वस्तुओं को लपेटने के लिए वस्तुओं का उपयोग करते समय , एक ऑपरेशन को रोकना, कुछ करना, और फिर "डिफ़ॉल्ट कार्य करना" करना बहुत आम है, जो आमतौर पर लिपटे ऑब्जेक्ट पर इंटरसेप्टेड ऑपरेशन को लागू करने के लिए होता है। उदाहरण के लिए, मान लें कि मैं किसी संपत्ति तक सभी संपत्ति को आसानी से प्रवेश करना चाहता हूं obj
:
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
Reflect
और Proxy
एपीआई संगठनों ने मिलकर डिजाइन किए गए थे , जिनमें से प्रत्येक के लिए ऐसी है कि Proxy
जाल, वहाँ एक इसी विधि से मौजूद है पर Reflect
कि "डिफ़ॉल्ट बात करता है"। इसलिए, जब भी आप खुद को एक प्रॉक्सी हैंडलर के अंदर "डिफॉल्ट" चीज करना चाहते हैं, तो सही बात यह है कि Reflect
ऑब्जेक्ट में संबंधित विधि को हमेशा कॉल करें :
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
वापसी के प्रकार जाल Reflect
के वापसी प्रकार के साथ संगत होने की गारंटी है Proxy
।
एक्सेसरों के इस-बाइंडिंग को नियंत्रित करें
ES5 में जेनेरिक प्रॉपर्टी एक्सेस या प्रॉपर्टी अपडेट करना काफी आसान है। उदाहरण के लिए:
var name = ...
obj[name]
obj[name] = value
Reflect.get
और Reflect.set
तरीकों आप एक ही बात करने के लिए है, लेकिन इसके अलावा एक एक अंतिम वैकल्पिक तर्क के रूप में स्वीकार कर पाएगी receiver
पैरामीटर है कि आप स्पष्ट रूप से सेट करने की अनुमति देता this
-binding जब संपत्ति है कि आप मिल / सेट एक्सेसर है:
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
यह कभी-कभी तब उपयोगी होता है जब आप रैपिंग कर रहे हों obj
और आप चाहते हैं कि एक्सेसर के भीतर कोई भी सेल्फ-अप अपने रैपर के पास दोबारा पहुंच जाए, जैसे कि यदि obj
इसे परिभाषित किया गया हो:
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
कॉलिंग Reflect.get(obj, "foo", wrapper)
का कारण होगा this.bar()
कॉल पर भेज पाने के लिए wrapper
।
विरासत से बचें __proto__
कुछ ब्राउज़रों पर, __proto__
एक विशेष संपत्ति के रूप में परिभाषित किया गया है जो किसी वस्तु के प्रोटोटाइप तक पहुंच प्रदान करता है। ईएस 5 Object.getPrototypeOf(obj)
ने प्रोटोटाइप को क्वेरी करने के लिए एक नई विधि का मानकीकरण किया। Reflect.getPrototypeOf(obj)
बिल्कुल वैसा ही करता है, सिवाय इसके कि वस्तु के प्रोटोटाइप को सेट करने के लिए Reflect
भी इसी Reflect.setPrototypeOf(obj, newProto)
को परिभाषित करता है । यह किसी वस्तु के प्रोटोटाइप को अपडेट करने का नया ES6-compliant तरीका है।
ध्यान दें: setPrototypeOf
यह भी मौजूद हैObject
(जैसा कि Knu की टिप्पणी द्वारा सही ढंग से बताया गया है )!
EDIT:
साइड-नोट (Q पर टिप्पणियों को संबोधित करते हुए): 'Q: ES6 मॉड्यूल बनाम HTML आयात' पर एक छोटा और सरल उत्तर है जो बताता है Realms
और Loader
वस्तुओं को बताता है।
इस लिंक द्वारा एक और स्पष्टीकरण दिया गया है :
एक वास्तविक वस्तु अपने स्वयं के वैश्विक वस्तु, मानक पुस्तकालय की प्रतिलिपि और "आंतरिक" (मानक वस्तुएं जो वैश्विक चर के लिए बाध्य नहीं हैं, जैसे Object.prototype के प्रारंभिक मूल्य) के साथ एक अलग वैश्विक वातावरण की धारणा को सार करती है।
एक्स्टेंसिबल वेब : यह <iframe>
DOM के बिना एक ही मूल के गतिशील समकक्ष है
।
हालांकि उल्लेख के लायक: यह सब अभी भी मसौदे में है, यह पत्थर में उत्कीर्ण एक विनिर्देश नहीं है! यह ES6 है, इसलिए ब्राउज़र-संगतता को ध्यान में रखें!
उम्मीद है की यह मदद करेगा!
Reflect
में सिर्फ वस्तुओंRealm
औरLoader
वस्तुओं के लिए एक कंटेनर है , लेकिन मुझे नहीं पता कि बाद वाले क्या करते हैं।