मुझे EcmaScript-5 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/hi/JavaScript/Reference/Global_Objects/Function/bind)। लेकिन वास्तविक जीवन स्थितियों में यह पूरी तरह से बेकार व्यवहार है ना? सवाल यह है कि यह बग है या फीचर? यदि यह एक बग है, तो इसका कहीं उल्लेख क्यों नहीं किया गया है? यदि यह एक विशेषता है, तो Google Chrome मूल "बाइंड" कार्यान्वयन के साथ बिल्कुल वैसा ही व्यवहार क्यों करता है?

इसे और स्पष्ट करने के लिए, मेरी राय में और क्या समझ में आएगा, यहां कोड स्निपेट है जो Function.prototype.bind को थोड़ा अलग तरीके से लागू करता है:

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;
    };
}

तो अब इसे आजमाएं:

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

मेरी राय में, "इस" को बदलना अधिक समझ में आता है ...

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

22
Ruslan 2 सितंबर 2011, 14:27
2
यह एक विशेषता है। यदि आप इसे ओवरराइड कर सकते हैं, तो यह वास्तव में "बाध्य" नहीं होगा, है ना? विवरण विनिर्देश में पाया जा सकता है: ecma262-5.com/ELS5_HTML.htm #धारा_15.3.4.5
 – 
Felix Kling
2 सितंबर 2011, 14:32
1
ज़रूर, लेकिन अगर ऐसा है, तो यह निर्धारित करने का तरीका क्या है कि फ़ंक्शन पहले से ही किसी चीज़ से बंधा हुआ है? या इसे फिर से बांधने का प्रयास करते समय यह कोई अपवाद क्यों नहीं फेंकता? बात यह है कि यह डीबग करना बेहद कठिन बनाता है, अगर आपको नहीं पता कि फ़ंक्शन बाध्य है या आप इसकी पहली प्रति से निपटते हैं। कल मेरे साथ ऐसा कुछ हुआ था, और मैंने समस्या की जड़ों का पता लगाने में लगभग एक दिन लगा दिया है...
 – 
Ruslan
2 सितंबर 2011, 15:25
1
वैसे भी, ऐसा लगता है कि कोई भी इस प्रश्न का उत्तर देने वाला नहीं है, इसलिए यदि किसी और को भी यही समस्या होगी, तो मैंने एक वर्कअराउंड बनाया है जिसे आप यहां पा सकते हैं: angrycoding.com/2011/09/to-bind-or-not- to-bind-that-is-in.html
 – 
Ruslan
2 सितंबर 2011, 22:34
वैसे भी आप किस तरह के जवाब की उम्मीद करेंगे? ऐसा लगता है कि आप कोई राय मांग रहे हैं, और ऐसे प्रश्नों को यहां हतोत्साहित किया जाता है। faq देखें।
 – 
Felix Kling
2 सितंबर 2011, 22:40
आह ठीक है क्षमा करें, मैं वास्तव में एक राय/सुझाव या कुछ भी ढूंढ रहा था जो मुझे इसके बारे में सबसे अच्छा समाधान खोजने का विचार देगा।
 – 
Ruslan
2 सितंबर 2011, 23:27

2 जवाब

सबसे बढ़िया उत्तर

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

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

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

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

14
Jeff Walden 6 सितंबर 2011, 05:30
उत्तर के लिए बहुत बहुत धन्यवाद, यह बहुत उपयोगी है। क्या आप कृपया ऐसे प्रस्ताव बनाने की प्रक्रिया का वर्णन कर सकते हैं? मुझे लगता है कि यह न केवल इस मामले के लिए उपयोगी होगा। पहले ही, आपका बहुत धन्यवाद।
 – 
Ruslan
6 सितंबर 2011, 08:13
मैं प्रक्रिया के बारे में अधिक जानने के लिए वास्तविक मानकीकरण कार्य में पर्याप्त रूप से शामिल नहीं हूं (मुझे विश्वास नहीं है कि यह पूरी तरह से औपचारिक है), लेकिन es-discuss से गेंद लुढ़क जाएगी। आप irc.mozilla.org पर #jslang चैनल में पूछने का प्रयास भी कर सकते हैं; सामान निर्दिष्ट करने में शामिल जेएस भाषा मानकवादियों के लिए यही एकमात्र वास्तविक hangout है, इसलिए वहां कोई भी पूर्ण प्रस्ताव कैसे प्राप्त कर सकता है।
 – 
Jeff Walden
23 सितंबर 2011, 00:20

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

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

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

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

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

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

2
Remember Monica 25 जुलाई 2013, 20:24
कोई यह तर्क दे सकता है कि बाइंड को इसे बिल्कुल भी नहीं छूना चाहिए, क्योंकि यह अन्य JS व्यवहार के अनुरूप होगा। हालांकि, मैं कहूंगा कि बाइंड के लिए सबसे आम एप्लिकेशन एक विधि कॉल को फ़ंक्शन कॉल में परिवर्तित करना है (जावास्क्रिप्ट में कोई अंतर्निहित विधि कॉल ऑब्जेक्ट नहीं है जिसे कॉलबैक के रूप में पारित किया जा सकता है - बाइंड इस छेद को भरता है)
 – 
Remember Monica
25 जुलाई 2013, 20:43
जहां तक ​​आपके अपेक्षित व्यवहार का संबंध है, आपको अपने आप से यह पूछना चाहिए कि आप इस मान के एक नए में पैच करने की अपेक्षा क्यों करते हैं, लेकिन नए तर्कों में पैच नहीं। यह काफी असंगत है।
 – 
Remember Monica
25 जुलाई 2013, 20:44
मैं पूरी तरह असहमत हूँ! जिस तरह से बाइंड () काम करता है वह बिल्कुल प्रति-सहज है। समस्या यह है कि आपको यह जानना है कि एक फ़ंक्शन पहले से ही बाध्य था। आप कभी भी यह सुनिश्चित नहीं कर सकते हैं कि .bind() को कॉल करते समय आपको किसी फ़ंक्शन से क्या मिलेगा। कभी-कभी आपको अपेक्षित व्यवहार मिलता है। कभी-कभी आप नहीं करते। यह इस तरह है: एक बाध्य कार्य में विशेष अर्थशास्त्र होता है और यह केवल एक कार्य नहीं होता है। मेरी राय में, एक बाउंड फ़ंक्शन केवल एक फ़ंक्शन होना चाहिए जिस पर आप Function.prototype से सभी सामग्री लागू कर सकते हैं। अन्यथा इसे एक अलग प्रोटोटाइप दें, उदा। BoundFunction और उसमें से .bind() हटा दें।
 – 
NicBright
3 अक्टूबर 2014, 10:29