2015-07-03 17 views
7

जब मैं यह answer पढ़ रहा हूं, तो var g = f.call.bind(f); खोजें। मैं इसे अपनी पहली दृष्टि से नहीं समझ सकता।जावास्क्रिप्ट में 'बंधन' और 'कॉल' चेनिंग?

तो क्या इसका कुछ प्रत्यक्ष अर्थ है, और इसमें कुछ उपयुक्त उपयोग परिदृश्य हैं?

और जब आप call(or apply) या bind या दोनों चेनिंग में उपयोग करते हैं, तो क्या होगा? क्या कुछ कानून हैं?

+0

क्या आपने कुछ तर्कों के साथ 'जी' को कॉल करने का प्रयास किया है और देखा है कि वे 'f' में कैसे पहुंच योग्य हैं? – Bergi

+0

[इस] (http://stackoverflow.com/q/24191701/1048572) पर एक नज़र डालें। – Bergi

उत्तर

4

var g = f.call.bind(f);। मैं इसे अपनी पहली दृष्टि से नहीं समझ सकता।

मुझे लगता है तुम दोनों .call() और .bind()Function तरीकों के साथ परिचित हो? खैर, यह f.call विधि f पर विधि को बांधता है।

ध्यान दें कि f.call सिर्फ Function.prototype.call है, इससे कोई फर्क नहीं पड़ता कि हम इसे f पर एक संपत्ति के रूप में एक्सेस करते हैं क्योंकि हम इसे यहां कॉल नहीं करते हैं।

तो क्या इसका कुछ प्रत्यक्ष अर्थ है?

यह जब हम ES6 बराबर देखो और अधिक स्पष्ट हो सकता है:

(Function.prototype.call).bind(f) // or 
(f.call).bind(f) // is basically 
(...args) => f.call(...args) // or more clear 
(ctx, ...args) => f.call(ctx, ...args) 

यह कुछ उचित उपयोग परिदृश्यों है?

ठीक है, अब आप जानते हैं कि यह क्या करता है, हाँ। यह एक प्रोटोटाइप विधि ले सकता है और इसे एक स्थिर कार्य में बदल देता है जो उदाहरण को पहला तर्क मानता है। एक उदाहरण:

function Example(n) { this.name = n; } 
Example.prototype.display = function() { console.log(this.name); } 

Example.display = Function.call.bind(Example.prototype.display); 

var e = new Example; 
e.display(); // is the same as 
Example.display(e); 

आगे call/apply/bind चेनिंग के लिए किसी भी कानून हैं?

हां: हमेशा के रूप में, श्रृंखला में केवल अंतिम संपत्ति को वास्तव में विधि के रूप में जाना जाता है। उपर्युक्त उदाहरण में, f.call.bind(…), Function.prototype.call.bind(…) या Function.call.apply.bind.call.bind(…) के बीच कोई अंतर नहीं है - यह हमेशा पर bind पर कॉल करता है।

हालांकि, उन्हें एक दूसरे के लिए तर्क के रूप में पास करके, आप somecrazythings कर सकते हैं जो कम या ज्यादा उपयोगी हैं।

2

अच्छा सवाल। चलो एक उदाहरण पर विचार करके शुरू करें जो पहले StackOverflow पर आ गया है: सरणी में सभी स्ट्रिंग्स को लोअरकेस में मैप करना। बेशक मैं

strings . map(function(string) { return string.toLowerCase(); }) 

लिख सकता है लेकिन यह थोड़ा वर्बोज़ लगता है।मैं नहीं बल्कि कम मुहावरा उपयोग करने के लिए

strings . map(CALL_LOWERCASE_WITH_ELT_AS_THIS) 

तो मैं

strings . map(String.prototype.toLowerCase) 

कोशिश कर सकते हैं लिखते हैं या कुछ पसंद करते हैं

strings . map(''.toLowerCase) 

क्योंकि ''.toLowerCase बिल्कुल String.prototype.toLowerCase के बराबर है।

लेकिन यह काम करेगा नहीं, ज़ाहिर है, क्योंकि map अपने this के रूप में नहीं अपना पहला तर्क के रूप में निर्दिष्ट समारोह के प्रत्येक तत्व से गुजरता है,। इसलिए, हमें किसी ऐसे फ़ंक्शन को निर्दिष्ट करने की आवश्यकता है जिसका पहला तर्क किसी अन्य फ़ंक्शन को this के रूप में कॉल करने के लिए उपयोग किया जाता है। जब function बुला

function.call(context) 

पहला तर्क call करने के लिए ("संदर्भ") this के रूप में प्रयोग किया जाता है: यह, ज़ाहिर है, वास्तव में क्या Function.call करता है।

तो, समस्या हल हो गई?

strings . map(''.toLowerCase.call) 

और लोगों को इस की कोशिश की और फिर क्यों यह काम नहीं किया है: हम सिर्फ कहने में सक्षम होना चाहिए। इसका कारण यह है कि भले ही हम calltoLowerCase को map पर कॉलबैक के रूप में पास कर रहे हैं, map को अभी भी कोई जानकारी नहीं है कि कॉलबैक ''.toLowerCase के this के साथ कॉल किया जाना चाहिए। ,

strings . map(''.toLowerCase.call, ''.toLowerCase) 

वास्तव में के बाद से call किसी भी समारोह वस्तु पर एक ही है: हम समारोह है, जो map के मामले में हम अपनी दूसरी "संदर्भ" तर्क के साथ क्या कर सकते हैं कॉल करने के लिए स्पष्ट रूप से उपयोग करने के लिए map जो this बताने की आवश्यकता , हम बस

strings . map(Function.call, ''.toLowerCase) 

यह काम करता है और काम खूबसूरती से किया जाता है करने के लिए इस आसान बनाने में कर सकते हैं।

हालांकि, जबकि map यह दूसरा "संदर्भ" तर्क के साथ कॉलबैक कॉल करने के लिए this निर्दिष्ट करने के लिए प्रदान करता है, कि कुछ हम सभी स्थितियों में उपलब्ध होने पर निर्भर कर सकता नहीं है। हमें यह कहने का एक और सामान्य तरीका चाहिए कि "एक ऐसा फ़ंक्शन बनाएं जो Function.call को कुछ विशेष फ़ंक्शन के साथ this" कहता है।

यह वही है जो bind करता है। यह कहते हैं, "एक समारोह लेने के लिए और एक और समारोह जो इसे एक विशेष this साथ कॉल कर":

function.bind(context) 

हमारे मामले में, हम क्या करना चाहते हैं "समारोह Function.call लेने के लिए और एक और समारोह जो इसके साथ कॉल करने के लिए है का this।यही कारण है कि बस

Function.call.bind(''.toLowerCase) 

अब हम दूसरा तर्क का उपयोग किए बिना map को यह पारित सकता है:

strings . map(Function.call.bind(''.toLowerCase)) 

बिल्कुल strings . map(Function.call, ''.toLowerCase) रूप में एक ही काम करता है यही कारण है, क्योंकि सामान्य रूप में map(fn, ctxt) ठीक map(fn.bind(ctxt)) के बराबर है।

निम्नलिखित टूट जाता है यह एक पठनीय रूप में नीचे, कदम से कदम:

Function .   // From the Function object 
    call .    // take the `call` method 
    bind(    // and make a new function which calls it with a 'this' of 
    ''.toLowerCase // `toLowerCase` 
) 

जब इस संरचना इस तरह के map के रूप में एक कॉलबैक के रूप में निर्दिष्ट किया जाता है, तो इसका मतलब है:

आह्वान call पहले तर्क के साथ ''.toLowerCasethis के रूप में पारित किया गया, जो call की परिभाषा के आधार पर toLowerCase को this के रूप में उस तर्क के साथ कॉल करने का मतलब है।

कुछ लोगों को

var call = Function.call; 
var toLowerCase = ''.toLowerCase; 

strings . map(call.bind(toLowerCase)) 

कह या, map द्वारा प्रदान की दूसरा तर्क का उपयोग करके यह थोड़ा आसान बनाने के लिए पसंद करते हैं बस

strings . map(call, toLowerCase) 

जो अंग्रेजी के रूप में लगभग पढ़ी जा सकती है: "मानचित्रके परिणाम के लिए प्रत्येक स्ट्रिंग आईएन टू लोवरकेस

एक और आम, संबंधित उपयोग केस एक वचन पर then में कॉलबैक निर्दिष्ट करेगा। निम्नलिखित कोड पर विचार करें:

promise . then(function(result) { result.frombulate(); }) 

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

promise . then(call.bind(frombulate)) 

call.bind मुहावरा के लिए अन्य उपयोग के मामलों रहे हैं, लेकिन इस सबसे आम लोगों में से एक है: एक कॉलबैक जिसका प्रभाव है पैरामीटर के साथ कुछ समारोह आह्वान करने के लिए परिभाषित कॉलबैक को this के रूप में पास किया गया।

ES6 वसा तीर कार्यों के साथ

, ज़ाहिर है, मैं लिख सकते हैं

promise . then(result => result.frombulate()) 

तो वहाँ है आशुलिपि call.bind(frombulate) द्वारा की पेशकश में अपेक्षाकृत कम लाभ, और यह अस्वीकार करने के लिए है कि वसा में तीर संस्करण अधिक है कठिन है bind का उपयोग कर उस से पठनीय।

निम्नलिखित प्रश्न भी ब्याज का हो सकता है: Array.map and lifted functions in Javascript

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