2012-05-15 12 views
10

में बाध्यकारी/लागू करने वाले कन्स्ट्रक्टर मैं जावास्क्रिप्ट कन्स्ट्रक्टर को तर्कसंगत संख्या के साथ कॉल करने के लिए समाधान ढूंढ रहा था, और कुछ अच्छे एसओ पोस्ट पाए, जिससे मुझे विश्वास हुआ कि इन तीनों कॉलों को भी काम करना चाहिए। हालांकि, राइनो और Node.js में कम से कम, वे नहीं है:जावास्क्रिप्ट

print(new f()) //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST) 

लेकिन अन्य दो नहीं:

print(new g()) //=> Thu Feb 01 1900 00:00:00 GMT-0500 (EST) 
print(new h()) //=> Wed Jun 01 1904 00:00:00 GMT-0400 (EST) 

1. f = Date.bind(Date, 2000,0,1) 
2. g = Date.bind.call(Date, 2000, 0, 1) 
3. h = Date.bind.apply(Date, [2000, 0, 1]) 

पहले एक वांछित परिणाम है

तो कुछ कहीं कहीं खराब हो गया है। क्या विचार? क्या apply, bind, और/या callnew जैसी चीजों को मिश्रण करना एक बुरा विचार है?

+0

वे सभी IE 8 में विफल हो जाते हैं क्योंकि कोई तारीख नहीं है। ;-) – RobG

+0

ऐसा लगता है कि यह 'बाइंड' का अनुचित उपयोग है। इसका उपयोग funcion ऑब्जेक्ट्स बनाने के लिए किया जाना चाहिए, लेकिन तिथियां दिनांक वस्तुएं हैं, फ़ंक्शंस नहीं हैं, और जिन्हें कॉल नहीं किया जा सकता है। इसके अलावा, बाध्य या कॉल या लागू करने के उपयोग के बिना, * यह * मान * दिनांक * वैसे भी है, तो बिंदु क्या है? अंत में, आप तारीख को एक कन्स्ट्रक्टर के रूप में नहीं बुला रहे हैं लेकिन एक समारोह के रूप में। – RobG

+0

निश्चित रूप से, दिनांक दिनांक वस्तुएं हैं, लेकिन तिथि स्वयं ही एक कार्य है, और यह तारीख है कि मैं बांधने की कोशिश कर रहा हूं। तिथि एक फ़ंक्शन है, इसलिए मैं इसे बांधता हूं और एक नया फ़ंक्शन प्राप्त करता हूं, जिसे मैं इसे 'नया' कहकर कन्स्ट्रक्टर के रूप में उपयोग करता हूं। जैसा कि मैंने प्रश्न के शीर्ष पर कहा था, वास्तविक बिंदु एक कन्स्ट्रक्टर को रनटाइम पर निर्धारित तर्कों की सूची के साथ कॉल करने में सक्षम होना है। –

उत्तर

23

previously accepted answer गलत था। आप नए कन्स्ट्रक्टर बनाने के लिए कन्स्ट्रक्टर के साथ बाध्य, कॉल और लागू कर सकते हैं - आपके परीक्षण में एकमात्र समस्या यह है कि आप भूल गए हैं कि bind.apply और bind.call आवेदन कर रहे हैं और बाध्य पर कॉल कर रहे हैं, न कि निर्माता स्वयं , इसलिए आपने गलत तर्क दिए।

f = Date.bind(null, 2000,0,1) 
g = Function.bind.call(Date, null, 2000, 0, 1) 
h = Function.bind.apply(Date, [ null, 2000, 0, 1 ]) 

new f() //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST) 
new g() //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST) 
new h() //=> Sat Jan 01 2000 00:00:00 GMT-0500 (EST) 

तीनों instanceof तिथि है।

कॉल के तर्क लागू करने के तर्कों के बाद निष्पादन संदर्भ हैं। आवेदन के तर्क निष्पादन संदर्भ और तर्कों की एक सरणी है। बाइंड के तर्क बाध्य करने के तर्कों के बाद निष्पादन संदर्भ हैं।

तो तर्क लागू करने के लिए, उदाहरण के लिए, संदर्भ के लिए पर लागू होते हैंबाँध (तिथि) कर रहे हैं एक सरणी जो बाँध के लिए बहस (ताकि पहली सरणी सदस्य बाँध के संदर्भ है, जिसके बाद तर्क)। यही कारण है कि यह कॉल करने या बाध्य करने के लिए भ्रमित है; दोनों को संदर्भ तर्क प्रदान करने के लिए अजीब लगता है।

ध्यान दें कि, जब रचनाकारों के साथ बांधते समय संदर्भ संदर्भ हमेशा अनदेखा किया जाता है क्योंकि 'नया' स्पष्ट रूप से एक नया संदर्भ बनाता है। जब मैं स्पष्ट तर्क रखने के लिए संदर्भ तर्क अप्रासंगिक है, तो मैं शून्य का उपयोग करता हूं, लेकिन यह कुछ भी हो सकता है।

इस बीच, इन उदाहरणों में आवेदन करें और कॉल करें, यह जानने की आवश्यकता है कि जिस संदर्भ में वे आवेदन/कॉल करना चाहते हैं वह दिनांक कार्य है। मैंने 'तिथि' को 'फंक्शन' पर स्विच किया जहां वास्तव में संदर्भ की आपूर्ति करने वाली चीज़ों को प्रकाशित करने में मदद करने के लिए संभव है। जब हम डेट.बिंड पर आवेदन करते हैं या कॉल करते हैं, तो हम वास्तव में कॉल ऑब्जेक्ट को अटैच किए गए बाइंड विधि पर लागू या कॉल कर रहे हैं। इस तरह के मामले में बांध विधि किसी भी समारोह से आ सकती है। यह संख्या.बिंद.call (तिथि, शून्य, 2000, 0, 1) हो सकता है और परिणाम बिल्कुल वही होगा।

यदि यह स्पष्ट नहीं है क्यों, निम्न उदाहरण के बीच अंतर पर विचार करें:

context.method(); 

और

var noLongerAMethod = context.method; 
noLongerAMethod(); 

दूसरे मामले में, विधि अपने मूलरूप से तलाक की गई है (.. जब तक कि यह पहले बाध्य नहीं था) और अगर यह आंतरिक रूप से 'इस' पर निर्भर था तो अलग-अलग व्यवहार करेगा। जब हम किसी भी दिए गए फ़ंक्शन को किसी संपत्ति को के रूप में सीधे निष्पादित करने के बजाय बाध्य करते हैं, तो यह फ़ंक्शन.प्रोटोटाइप पर जेनेरिक बाइंड विधि के लिए बस एक और सूचक है।

व्यक्तिगत रूप से मुझे नहीं लगता कि मुझे कभी भी कॉल करने या बाध्य करने की आवश्यकता है, और ऐसी स्थिति की कल्पना करना मुश्किल है जिसके लिए यह एक अच्छा समाधान होगा, लेकिन नए कन्स्ट्रक्टर बनाने के लिए बाध्यकारी कन्स्ट्रक्टर मुझे कुछ मिला है अवसर पर बहुत उपयोगी है। किसी भी मामले में यह एक मजेदार पहेली है।

+0

यह एक बहुत ही उपयोगी प्रतिक्रिया थी। धन्यवाद! –

5

bind और apply/call केवल समारोह नहीं बल्कि निर्माता, इसलिए देशी तरीकों यदि आप ऐसा नहीं कर सकते हैं के साथ मूल रूप से करने के लिए काम मंगलाचरण काम करता है, एक तरह से एक bindConstruct विधि लिखने के लिए है लेकिन यह अतिरिक्त जटिलता शामिल हो सकता है:

function bindConstruct(fn) { 
    // since constructor always accepts a static this value 
    // so bindConstruct cannot specify this 
    var extraArgs = [].slice.call(arguments, 1); 

    // create a 'subclass' of fn 
    function sub() { 
     var args = extraArgs.concat([].slice.call(arguments)); 
     fn.apply(this, args); 
    } 
    sub.prototype = fn.prototype; 
    sub.prototype.constructor = sub; 

    return sub; 
} 

यह वास्तव में, आपके निर्माता को उपclass बनाता है।

फिर अपने कोड:

var MyClass = function(x, y) { 
    console.log(arguments); 
    console.log(x + y); 
} 
var BindedMyClass = bindConstruct(MyClass, 1, 2, 3); 
var c = new BindedMyClass(4, 5); 
console.log(c instanceof MyClass); 
console.log(c instanceof BindedMyClass); 

तुम भी Function.prototype करने के लिए या देशी bind समारोह के लिए एक विस्तार के रूप में इस समारोह लिख सकते हैं।

+1

धन्यवाद, लेकिन दुख की बात है, यह ठीक से काम नहीं करता है, या तो। 'टाइप एरर: विधि को असंगत ऑब्जेक्ट पर बुलाया गया विधि' के साथ मेरे नए "डेट सबक्लास" फ़ंक्शन के साथ बनाई गई किसी भी ऑब्जेक्ट पर डेट विधियां विफल होती हैं। इस प्रकार एक बार फिर प्रदर्शित होता है कि जावास्क्रिप्ट में वास्तव में सबक्लास नहीं हैं। या कक्षाएं, उस मामले के लिए ... –

+0

"बाध्य और लागू/कॉल केवल कार्य करने के लिए कार्य आमंत्रण कार्य करता है लेकिन कन्स्ट्रक्टर नहीं" बस सत्य नहीं है; निचे देखो। – Semicolon

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^