2013-10-29 5 views
7
function foo(){ 
    console.log('foo', this); 
} 

foo(); 
foo.call({ bar: 1 }); 
foo.apply([{ bar: 1 }]); 

वहाँ foo() अगर पता करने के लिए किसी भी तरह से एक सामान्य आह्वान या call/apply का उपयोग कर बुलाया गया था है?कैसे जांच करने के लिए एक समारोह कॉल का उपयोग कर कहा जाता है यदि/लागू

http://jsfiddle.net/H4Awm/1/

+1

मैं कहूंगा कि आपका मतलब है 'foo.call (यह, {बार: 1}));' और 'foo.apply (यह, [{बार: 1}])); सही? –

उत्तर

3

नहीं, आप एक समारोह call/apply या सामान्य रूप से से कहा जाता है, तो पता नहीं लगा सकते।

वे जादुई प्राणियों नहीं हैं, वे सभी तर्क और this मान निर्धारित करते हैं। एक subtle difference है जब यह अपरिभाषित/अविकसित मानों की बात आती है लेकिन यह है।

सभी .apply और .call ES5 में क्या है:

वापसी, समारोह के आंतरिक विधि [[कॉल]] बुला thisArg यह मान और तर्कों की सूची के रूप में argList के रूप में उपलब्ध कराने का परिणाम है।

यह सही ढंग से आंतरिक caller विशेषता सेट तो कुछ this तरह अनुभवहीन कार्य नहीं करेगा। वास्तविक आंतरिक यांत्रिकी ([[Call]] आंतरिक समारोह) संकेत है कि यह का उपयोग कर कहा जाता है का कोई भी तरीका प्रदान नहीं करते हैं -

2

जब तक आप Function.prototype.call और Function.prototype.apply को फिर से परिभाषित (और अपने कार्य करने के लिए एक और तर्क पारित), वहाँ ऐसा करने का कोई तरीका नहीं है ()

एक general function call के लिए और Function.prototype.apply के लिए विनिर्देश की तुलना करें - प्रत्येक वास्तव में एक ही तरीके से समारोह के आंतरिक कोड कहते हैं, और कोई बाहरी संपत्ति सेट है कि आप देने के लिए है कि क्या कहा जाता है में सक्षम है कि या नहीं का उपयोग कर रहा है।

आंतरिक समारोह [[Call]] के लिए विनिर्देश देखें:

13.2.1 [[Call]]

जब एक समारोह वस्तु एफ एक यह मान और तर्क, की सूची के साथ कहा जाता है के लिए [[Call]] आंतरिक विधि निम्नलिखित कदम उठाए गए हैं:

  1. funcCtx को F के मान का उपयोग करके फ़ंक्शन कोड के लिए एक नया निष्पादन संदर्भ स्थापित करने का परिणाम होना चाहिए [[औपचारिक पैरामीटर]] आंतरिक संपत्ति, उत्तीर्ण तर्क सूची तर्क, और यह मान 10.4.3 में वर्णित है।
  2. परिणामस्वरूप फंक्शनबॉडी का मूल्यांकन करने का नतीजा है जो एफ की [[कोड]] आंतरिक संपत्ति का मूल्य है। यदि एफ में [[कोड]] आंतरिक संपत्ति नहीं है या यदि इसका मान एक खाली फ़ंक्शनबॉडी है, तो परिणाम (सामान्य, अपरिभाषित, खाली) है।
  3. निष्पादन संदर्भ funcCtx से बाहर निकलें, पिछले निष्पादन संदर्भ को पुनर्स्थापित करना।
  4. यदि परिणाम। टाइप फेंक दिया जाता है तो परिणाम निकाल दें .value।
  5. यदि परिणाम। प्रकार वापस आ गया है तो परिणाम वापसी करें। मूल्य।
  6. अन्यथा परिणाम। टाइप सामान्य होना चाहिए। अपरिभाषित वापसी।

वहाँ है कि क्या यह call/apply या नहीं का उपयोग कर कहा जाता है से एक समारोह के संचालन को बदलने के लिए कोई प्रावधान नहीं है - केवल बात यह है कि बदल जाता है कि वह क्या करता समारोह के लिए ही तर्क हैं और क्या this है समारोह के भीतर होना था।

+0

'जब तक आप फ़ंक्शन.प्रोटोटाइप.call' को हाइजैक नहीं करते हैं - मुझे इस तरह की चीज लागू करने में खुशी होगी - मुझे विश्वास है कि यह अपेक्षाकृत अधिक कठिन साबित होगा क्योंकि' call' आंतरिक रूप से भी उपयोग किया जाता है। –

+0

@ बेंजामिनग्रेनबाम: मेरा मतलब सिर्फ एक रैपर के रूप में कार्य को फिर से परिभाषित करना है, मुझे इसे और स्पष्ट करना चाहिए। –

-1

मैं इस कारण की जांच नहीं कर सकता हूं, लेकिन आप this === window की तुलना करके जांच सकते हैं, क्योंकि यह डिफ़ॉल्ट दायरा (ब्राउज़र आधारित जावास्क्रिप्ट मानते हुए) है, लेकिन इसे फ़ू को कॉल करके फिक्र किया जा सकता है foo.call(window) जो मूल रूप से foo() पर कॉल कर रहा है सामान्य रूप से कर रहा है।

यह शायद अन्य वस्तुओं या प्रोटोटाइप के गुणों के लिए window का उपयोग करके काम नहीं करेगा।

1

मुझे आशा है कि यह आपकी समस्या का समाधान:

function foo(){ 
    console.log('foo', this); 

    if (typeof this.length === "number") { 
     //function has been apply 
    } else { 
     //function has been call 
    } 
} 

foo(); 
foo.call({ bar: 1 }); 
foo.apply([{ bar: 1 }]); 
+0

इसके साथ समस्या यह है कि आप 'लागू' के लिए एक सरणी पास कर रहे हैं, और 'कॉल' के लिए एक ऑब्जेक्ट पास कर रहे हैं। क्या होता है जब आप दोनों के लिए ऑब्जेक्ट पास करते हैं? –

1

कुछ इस तरह का प्रयास करें:

function foo(){ 

    console.log('foo', this); 
    console.log(arguments); 
} 
Function.prototype._apply = Function.prototype.apply; 
Function.prototype.apply = function(ths,args){ 
    args.unshift('apply'); 
    this._apply(ths,args); 
}; 

foo(); 
foo.call(this, { bar: 1 }); 
foo.apply(this, [{ bar: 1 }]); 
1

गंदा, गंदा हैक:

function foo() { 
    var isNatural = !/foo\.(call|apply)/.test("" + foo.caller) 
    console.log(isNatural ? "foo()" : "foo.{call,apply}()") 
} 

function caller1() { 
    foo() 
} 
function caller2() { 
    foo.call(null, { bar: 1 }) 
} 
function caller3() { 
    foo.apply(null, [{ bar: 1 }]) 
} 

caller1() 
caller2() 
caller3() 

यह सिर्फ सोचा के लिए भोजन है। उत्पादन पर इसका इस्तेमाल न करें।

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

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