जावास्क्रिप्ट के शुरुआती संस्करणों ने नाम की अभिव्यक्ति को अनुमति नहीं दी, और इस वजह से हम एक पुनरावर्ती फ़ंक्शन अभिव्यक्ति नहीं बना सके:
// This snippet will work:
function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
}
[1,2,3,4,5].map(factorial);
// But this snippet will not:
[1,2,3,4,5].map(function(n) {
return (!(n>1))? 1 : /* what goes here? */ (n-1)*n;
});
इसके आसपास जाने के लिए, arguments.callee
हमें इसमें जोड़ा गया था:
[1,2,3,4,5].map(function(n) {
return (!(n>1))? 1 : arguments.callee(n-1)*n;
});
हालाँकि यह वास्तव में एक बुरा समाधान था क्योंकि यह (अन्य तर्कों, कैली और कॉलर मुद्दों के साथ संयोजन में) सामान्य मामले में इनलाइनिंग और पूंछ पुनरावृत्ति को असंभव बनाता है (आप इसे ट्रेसिंग आदि के माध्यम से चुनिंदा मामलों में प्राप्त कर सकते हैं, लेकिन सबसे अच्छा कोड भी चेक के कारण उप इष्टतम है जो अन्यथा आवश्यक नहीं होगा)। अन्य प्रमुख मुद्दा यह है कि पुनरावर्ती कॉल को एक अलग this
मूल्य मिलेगा , उदाहरण के लिए:
var global = this;
var sillyFunction = function (recursed) {
if (!recursed)
return arguments.callee(true);
if (this !== global)
alert("This is: " + this);
else
alert("This is the global");
}
sillyFunction();
किसी भी तरह, EcmaScript 3 ने इन समस्याओं को हल करने के लिए फ़ंक्शन फ़ंक्शन नाम की अनुमति दी है, जैसे:
[1,2,3,4,5].map(function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
});
इसके कई लाभ हैं:
फ़ंक्शन को आपके कोड के अंदर से किसी भी अन्य की तरह कहा जा सकता है।
यह नाम स्थान को प्रदूषित नहीं करता है।
मूल्य this
नहीं बदलता है।
यह अधिक प्रदर्शन करने वाला है ( तर्कों को एक्सेस करना महंगा है)।
ओह,
बस एहसास है कि सब कुछ के अलावा सवाल के बारे में था arguments.callee.caller
, या अधिक विशेष रूप से Function.caller
।
किसी भी समय आप स्टैक पर किसी भी फ़ंक्शन का सबसे गहरा कॉलर पा सकते हैं, और जैसा कि मैंने ऊपर कहा, कॉल स्टैक को देखने का एक ही प्रमुख प्रभाव पड़ता है: यह बड़ी संख्या में अनुकूलन असंभव बनाता है, या बहुत अधिक कठिन।
उदाहरण के लिए। अगर हम गारंटी नहीं दे सकते कि कोई फ़ंक्शन f
किसी अज्ञात फ़ंक्शन को कॉल नहीं करेगा, तो यह इनलाइन संभव नहीं है f
। मूल रूप से इसका मतलब यह है कि किसी भी कॉल साइट जो संभवतः तुच्छ हो सकती है, बड़ी संख्या में गार्ड जमा करती है, ले:
function f(a, b, c, d, e) { return a ? b * c : d * e; }
यदि जेएस दुभाषिया यह गारंटी नहीं दे सकता कि सभी प्रदान किए गए तर्क उस बिंदु पर संख्याएं हैं, जिस पर कॉल किया गया है, तो इसे या तो इनकोड कोड से पहले सभी तर्कों के लिए चेक डालने की आवश्यकता है, या यह फ़ंक्शन को इनलाइन नहीं कर सकता है।
अब इस विशेष मामले में एक स्मार्ट दुभाषिया चेक को फिर से व्यवस्थित करने में सक्षम होना चाहिए और किसी भी मान की जांच न करें जिसका उपयोग नहीं किया जाएगा। हालाँकि कई मामलों में यह संभव नहीं है और इसलिए यह असंभव हो जाता है।