2011-09-02 2 views
22

मुझे EcmaScript-5 Function.prototype.bind कार्यान्वयन के बारे में बहुत दिलचस्प सवाल है। आमतौर पर जब आप बाँध का उपयोग करें, आप इसे इस तरह से कार्य करें:Function.prototype.bind

var myFunction = function() { 
    alert(this); 
}.bind(123); 

// will alert 123 
myFunction(); 

ठीक है तो कि अच्छा है, लेकिन क्या होने जब हम ऐसा करते हैं लगता है?

// rebind binded function 
myFunction = myFunction.bind('foobar'); 
// will alert... 123! 
myFunction(); 

मैं समझता हूँ कि यह कैसे Function.prototype.bind कार्यान्वित किया जाता है (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind) के मामले में पूरी तरह से तार्किक व्यवहार है। लेकिन वास्तविक जीवन की स्थिति में यह पूरी तरह से बेकार व्यवहार है ना? सवाल यह है: क्या यह बग या फीचर है? अगर यह एक बग है, तो इसका उल्लेख क्यों नहीं किया गया है? यदि यह एक सुविधा है, तो फिर मूल "बाइंड" कार्यान्वयन के साथ Google क्रोम बिल्कुल वही व्यवहार करता है?

if (!Function.prototype.bind) { 
    Function.prototype.bind = function() { 
     var funcObj = this; 
     var original = funcObj; 
     var extraArgs = Array.prototype.slice.call(arguments); 
     var thisObj = extraArgs.shift(); 
     var func = function() { 
      var thatObj = thisObj; 
      return original.apply(thatObj, extraArgs.concat(
       Array.prototype.slice.call(
        arguments, extraArgs.length 
       ) 
      )); 
     }; 
     func.bind = function() { 
      var args = Array.prototype.slice.call(arguments); 
      return Function.prototype.bind.apply(funcObj, args); 
     } 
     return func; 
    }; 
} 

तो अब इस कोशिश:

बनाने के लिए इसे और अधिक स्पष्ट है, क्या मेरी राय में अधिक समझ बनाने हैं, तो यहां कोड स्निपेट कि Function.prototype.bind लागू करता है अलग ढंग से एक छोटा सा है

// rebind binded function 
myFunction = myFunction.bind('foobar'); 
// will alert... "foobar" 
myFunction(); 

मेरी राय में, की जगह "इस" अधिक समझ में आता है ...

तो क्या तुम लोग इसके बारे में क्या सोचते हैं?

+2

यह एक सुविधा है। यदि आप इसे ओवरराइड कर सकते हैं, तो यह वास्तव में "बाध्य" नहीं होगा, है ना? विवरण विनिर्देशन में पाया जा सकता है: http://ecma262-5.com/ELS5_HTML.htm#Section_15.3.4.5 –

+1

निश्चित रूप से लेकिन यदि यह है, तो यह निर्धारित करने का तरीका क्या है कि फ़ंक्शन पहले से ही सीमित है या नहीं कुछ कुछ? या फिर इसे पुनर्निर्मित करने का प्रयास करते समय यह कोई अपवाद क्यों नहीं फेंकता है? बात यह है कि यह डीबग करना बेहद मुश्किल बनाता है, अगर आपको नहीं पता कि फ़ंक्शन बाध्य है या आप इसकी पहली प्रतिलिपि से निपटते हैं। कल मेरे साथ ऐसा हुआ, और मैंने समस्या की जड़ें जानने के लिए लगभग एक दिन व्यतीत किया है ... – Ruslan

+1

वैसे भी, ऐसा लगता है कि कोई भी इस सवाल का जवाब नहीं दे रहा है, इसलिए अगर किसी और के पास होगा एक ही समस्या, मैंने एक वर्कअराउड बनाया है जिसे आप यहां पा सकते हैं: http://www.angrycoding.com/2011/09/to-bind-or-not-to-bind-that-is-in.html – Ruslan

उत्तर

14

Function.prototype.bind के लिए उदाहरण विभिन्न जेएस ढांचे में विचार का कार्यान्वयन था। मेरे सबसे अच्छे ज्ञान के लिए, उनमें से कोई भी this-बाध्यकारी द्वारा बाध्यकारी होने की अनुमति नहीं देता है। आप यह भी पूछ सकते हैं कि उनमें से कोई भी इस बाध्यकारी परिवर्तन की अनुमति क्यों नहीं देता है, यह पूछने के लिए कि ES5 इसे क्यों अनुमति नहीं देता है।

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

मुझे इस मुद्दे पर चर्चा होने पर याद नहीं है bind निर्दिष्ट किया जा रहा था। हालांकि, जब मैं इस सामान को धोया गया था तब मैं ई-चर्चा मेलिंग सूची पर विशेष रूप से ध्यान नहीं दे रहा था। उस ने कहा, मुझे विश्वास नहीं है कि ईएस 5 इस क्षेत्र में नवाचार करने की तलाश में था, एक वाक्यांश उधार लेने के लिए, "एक गायपा दाढ़ी"।

यदि आप पर्याप्त विस्तृत प्रस्ताव लिखते हैं, तो आप इन चिंताओं को हल करने के लिए कुछ आत्मनिर्भर तरीकों का प्रस्ताव दे सकते हैं। दूसरी तरफ, बाध्यकारी सूचना-छिपाने की व्यवस्था का एक रूप है, जो इसके गोद लेने के खिलाफ कटौती करेगा। यदि आपके पास समय है, तो कुछ प्रस्ताव देने का प्रयास करना संभव हो सकता है। मेरा अनुमान है कि सूचना-छिपाने की चिंता एक प्रस्ताव को अपनाए जाने से रोक देगा। लेकिन यह सिर्फ एक अनुमान है कि गलत हो सकता है। पता लगाने के लिए केवल एक ही रास्ता ...

+0

उत्तर के लिए बहुत बहुत धन्यवाद, यह बहुत उपयोगी है। क्या आप कृपया ऐसे प्रस्ताव बनाने की प्रक्रिया का वर्णन कर सकते हैं? मुझे लगता है कि यह न केवल इस मामले के लिए उपयोगी होगा। पहले ही, आपका बहुत धन्यवाद। – Ruslan

+0

मैं प्रक्रिया के बारे में बहुत कुछ जानने के लिए वास्तविक मानकीकरण कार्य में पर्याप्त शामिल नहीं हूं (मुझे विश्वास नहीं है कि पूरी तरह से औपचारिक है), लेकिन [es-चर्चा] पर मेल भेजना (https://mail.mozilla.org/listinfo/es-चर्चा) गेंद रोलिंग मिल जाएगा। आप irc.mozilla.org पर #jslang चैनल में पूछने का भी प्रयास कर सकते हैं; यह एकमात्र असली hangout है जिसे मैं जेएस भाषा मानकों के लिए सामान निर्दिष्ट करने में शामिल करता हूं, इसलिए कोई भी अच्छी तरह से जान सकता है कि एक पूर्ण प्रस्ताव कैसे प्राप्त किया जाए। –

2

जब आप कोई फ़ंक्शन बाध्य करते हैं, तो आप एक नया फ़ंक्शन मांगते हैं जो इस छद्म तर्क को अनदेखा करता है और मूल फ़ंक्शन को इसके लिए निश्चित मान के साथ कॉल करता है।

इस फ़ंक्शन को बाध्य करना एक और समय बिल्कुल वही व्यवहार है। यदि बांध किसी भी तरह से इसमें नए तरीके से पैच करेगा, तो इसे पहले से ही बाध्य-कार्यों के लिए विशेष मामला होना होगा।

दूसरे शब्दों में, बाध्य "सामान्य" कार्यों पर बिल्कुल काम करता है क्योंकि यह बाध्य द्वारा किए गए कार्यों पर काम करता है, और ओवरराइडिंग कारकों की अनुपस्थिति में, यह एक कम काम की अर्थपूर्ण जटिलता को रखने के लिए अच्छी इंजीनियरिंग है - यह आसान है यह याद रखने के लिए कि किसी फ़ंक्शन में क्या बाध्य होता है यदि यह सभी इनपुट फ़ंक्शंस को बिल्कुल उसी तरह से व्यवहार करता है, विशेष रूप से कुछ इनपुट फ़ंक्शंस का इलाज करने के विपरीत।

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

इस प्रकार, इस बात का कोई रहस्य नहीं है कि इसे मानकीकृत या आविष्कार क्यों किया गया था: बाइंड एक ऐसा कार्य देता है जो एक नया प्रदान करता है और तर्क प्रस्तुत करता है, और सभी कार्यों पर भी काम करता है। सबसे आसान संभव अर्थपूर्ण।

केवल इस तरह से यह वास्तव में उपयोग करने के लिए सुरक्षित है - यदि बांध पहले से ही बाध्य कार्यों और "सामान्य" वाले लोगों के बीच एक अंतर बनाएगा, तो बाध्यकारी से पहले परीक्षण करना होगा। एक अच्छा उदाहरण jQuery.each होगा, जो एक नया पास करता है। यदि बाध्य विशेष बाध्य कार्य करेगा, तो jQuery.each में बाध्य फ़ंक्शन को पास करने का कोई सुरक्षित तरीका नहीं होगा, क्योंकि यह प्रत्येक कॉल पर ओवरराइट किया जाएगा। इसे ठीक करने के लिए, jQuery.each को किसी भी तरह बाध्य कार्यों को विशेष करना होगा।

+0

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

+0

आपके अपेक्षित व्यवहार के लिए , आपको खुद से पूछना चाहिए कि आप इस मूल्य को नए में पैच करने की अपेक्षा क्यों करते हैं, लेकिन नए तर्कों में पैच नहीं करते हैं। यह काफी असंगत है। –

+0

मैं पूरी तरह से असहमत हूं! जिस तरह से बांध() काम बिल्कुल काउंटर-सहज है। समस्या यह है कि आपको पता होना चाहिए कि एक समारोह पहले से ही बंधे थे। आप यह सुनिश्चित नहीं कर सकते कि उस पर .bind() को कॉल करते समय आपको फ़ंक्शन से क्या मिलेगा। कभी-कभी आपको अपेक्षित व्यवहार मिलता है।कभी-कभी आप नहीं करते हैं। यह इस तरह है: एक बाध्य समारोह में विशेष अर्थशास्त्र है और यह केवल एक समारोह नहीं है। मेरी राय में, एक बाध्य कार्य केवल एक ऐसा कार्य होना चाहिए जिस पर आप Function.prototype से सभी सामग्री लागू कर सकते हैं। अन्यथा इसे एक अलग प्रोटोटाइप दें, उदा। बाउंडफंक्शन और इससे हटाएं।)()। – NicBright