function main()
{
Hello();
}
function Hello()
{
// How do you find out the caller function is 'main'?
}
क्या कॉल स्टैक का पता लगाने का एक तरीका है?
function main()
{
Hello();
}
function Hello()
{
// How do you find out the caller function is 'main'?
}
क्या कॉल स्टैक का पता लगाने का एक तरीका है?
जवाबों:
function Hello()
{
alert("caller is " + Hello.caller);
}
ध्यान दें कि यह सुविधा गैर-मानक है , इससे Function.caller
:
गैर-मानक
यह सुविधा गैर-मानक है और एक मानक ट्रैक पर नहीं है। वेब का सामना करने वाले उत्पादन साइटों पर इसका उपयोग न करें: यह प्रत्येक उपयोगकर्ता के लिए काम नहीं करेगा। कार्यान्वयन के बीच बड़ी असंगतताएं भी हो सकती हैं और भविष्य में व्यवहार बदल सकता है।
2008 से निम्नलिखित पुराना उत्तर है, जो अब आधुनिक जावास्क्रिप्ट में समर्थित नहीं है:
function Hello()
{
alert("caller is " + arguments.callee.caller.toString());
}
arguments.callee.caller.name
फ़ंक्शन का नाम मिलेगा।
'use strict';
मदद मिल सकती है।
arguments
सख्त मोड में एक फ़ंक्शन के भीतर से पहुँचा जा सकता है, यह है कि यह पदावनत करने के लिए बेवकूफ होगा। सिर्फ बाहर से function.arguments से नहीं। इसके अलावा, यदि आपके पास एक नामित तर्क है, तो इसके तर्क [i] रूप को फ़ंक्शन के अंदर नामित संस्करण में किए गए परिवर्तनों को ट्रैक नहीं करेंगे।
आप ब्राउज़र विशिष्ट कोड का उपयोग करके संपूर्ण स्टैक ट्रेस पा सकते हैं। अच्छी बात यह है कि किसी ने इसे पहले ही बना लिया है ; यहाँ GitHub पर प्रोजेक्ट कोड है ।
लेकिन सभी समाचार अच्छे नहीं हैं:
स्टैक ट्रेस प्राप्त करना वास्तव में धीमा है इसलिए सावधान रहें ( इसे और अधिक पढ़ें )।
स्टैक ट्रेस करने योग्य होने के लिए आपको फ़ंक्शन नामों को परिभाषित करने की आवश्यकता होगी। क्योंकि अगर आपके पास इस तरह का कोड है:
var Klass = function kls() {
this.Hello = function() { alert(printStackTrace().join('\n\n')); };
}
new Klass().Hello();
Google Chrome अलर्ट करेगा ... kls.Hello ( ...
लेकिन अधिकांश ब्राउज़र कीवर्ड के ठीक बाद एक फ़ंक्शन नाम की उम्मीद function
करेंगे और इसे एक अनाम फ़ंक्शन के रूप में मानेंगे। Klass
यदि आप नाम नहीं देते हैं तो भी क्रोम नाम का उपयोग नहीं कर पाएगाkls
फ़ंक्शन को ।
और वैसे भी, आप इस विकल्प को प्रिंटस्टैक में पास कर सकते हैं, {guess: true}
लेकिन मुझे ऐसा करने से कोई वास्तविक सुधार नहीं मिला।
सभी ब्राउज़र आपको एक ही जानकारी नहीं देते हैं। वह है, पैरामीटर, कोड कॉलम इत्यादि।
वैसे, यदि आप केवल कॉलर फ़ंक्शन का नाम चाहते हैं (अधिकांश ब्राउज़र में, लेकिन IE नहीं) तो आप उपयोग कर सकते हैं:
arguments.callee.caller.name
लेकिन ध्यान दें कि यह नाम function
कीवर्ड के बाद एक होगा । मुझे पूरे फ़ंक्शन का कोड प्राप्त किए बिना इससे अधिक पाने के लिए कोई रास्ता नहीं मिला (Google क्रोम पर भी)।
और बाकी बेहतरीन जवाबों को संक्षेप में (पाब्लो कैबरेरा, नोरडाइन और ग्रेग हेगिल द्वारा)। एकमात्र क्रॉस-ब्राउज़र और वास्तव में सुरक्षित चीज़ जिसका आप उपयोग कर सकते हैं:
arguments.callee.caller.toString();
जो कॉलर फ़ंक्शन का कोड दिखाएगा । अफसोस की बात है, यह मेरे लिए पर्याप्त नहीं है, और यही कारण है कि मैं आपको स्टैकट्रेस और कॉलर फ़ंक्शन नाम के लिए टिप्स देता हूं (हालांकि वे क्रॉस-ब्राउज़र नहीं हैं)।
Function.caller
हालांकि, सख्त मोड में काम नहीं करेगा।
मुझे पता है कि आपने "जावास्क्रिप्ट में" का उल्लेख किया है, लेकिन यदि उद्देश्य डिबगिंग है, तो मुझे लगता है कि आपके ब्राउज़र के डेवलपर टूल का उपयोग करना आसान है। यह Chrome में कैसा दिखता है: बस उस डिबगर को छोड़ दें जहाँ आप स्टैक की जांच करना चाहते हैं।
फिर से तैयार करना (और इसे स्पष्ट करना) ...
यह कोड:
function Hello() {
alert("caller is " + arguments.callee.caller.toString());
}
इसके बराबर है:
function Hello() {
alert("caller is " + Hello.caller.toString());
}
स्पष्ट रूप से पहला बिट अधिक पोर्टेबल है, चूंकि आप फ़ंक्शन का नाम बदल सकते हैं, "हैलो" से "सीआओ" तक कह सकते हैं, और अभी भी पूरी तरह से काम करने के लिए प्राप्त कर सकते हैं।
उत्तरार्द्ध में, यदि आप चालान किए गए फ़ंक्शन (हैलो) के नाम को रिफलेक्टर करने का निर्णय लेते हैं, तो आपको इसकी सभी घटनाओं को बदलना होगा :(
आप पूर्ण स्टैकट्रेस प्राप्त कर सकते हैं:
arguments.callee.caller
arguments.callee.caller.caller
arguments.callee.caller.caller.caller
जब तक कॉलर है null
।
नोट: यह पुनरावर्ती कार्यों पर एक अनंत लूप का कारण बनता है।
मैं आमतौर पर (new Error()).stack
क्रोम में उपयोग करता हूं । अच्छी बात यह है कि यह आपको लाइन नंबर भी देता है, जहां कॉल करने वाले को फ़ंक्शन कहा जाता है। नकारात्मक पक्ष यह है कि यह स्टैक की लंबाई 10 तक सीमित करता है, यही कारण है कि मैं इस पृष्ठ पर पहले स्थान पर आया था।
(मैं निष्पादन के दौरान एक निम्न-स्तर के निर्माणकर्ता में कॉलस्टैक्स इकट्ठा करने के लिए इसका उपयोग कर रहा हूं, बाद में देखने और डीबग करने के लिए, इसलिए एक ब्रेकपॉइंट सेट करना उपयोग नहीं है क्योंकि यह हजारों बार हिट हो जाएगा)
'use strict';
वह जगह पर हो। मुझे आवश्यक जानकारी दी - धन्यवाद!
यदि आप इसे IE <11 में नहीं चलाने जा रहे हैं तो कंसोल। () सूट करेगा।
function main() {
Hello();
}
function Hello() {
console.trace()
}
main()
// Hello @ VM261:9
// main @ VM261:4
आप फ़ंक्शन को प्राप्त करने के लिए फ़ंक्शन.कॉलर का उपयोग कर सकते हैं। तर्क का उपयोग करते हुए पुरानी पद्धति। पुरानी को अप्रचलित माना जाता है।
निम्न कोड इसके उपयोग को दिखाता है:
function Hello() { return Hello.caller;}
Hello2 = function NamedFunc() { return NamedFunc.caller; };
function main()
{
Hello(); //both return main()
Hello2();
}
अप्रचलित तर्क के बारे में नोट्स। पोस्टर: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller
जागरूक रहें। फॉलर गैर-मानक है: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller
Cannot access caller property of a strict mode function
function Hello() {
alert(Hello.caller);
}
arguments.callee.caller.toString()
यह *arguments.callee.caller
तब से उपयोग करने के लिए सुरक्षित है जब arguments.caller
से पदावनत ...
arguments.callee
ES5 में भी पदावनत किया गया, और सख्त मोड में हटा दिया गया।
ऐसा लगता है कि यह काफी सुलझा हुआ सवाल है, लेकिन मुझे हाल ही में पता चला है कि कैली को 'सख्त मोड' में अनुमति नहीं है, इसलिए अपने स्वयं के उपयोग के लिए मैंने एक वर्ग लिखा है, जहां से इसे कहा जाता है। यह एक छोटे सहायक का हिस्सा है और यदि आप कॉलर के स्टैक ट्रेस को वापस करने के लिए उपयोग किए जाने वाले ऑफसेट को कोड स्टैंडअलोन बदलने के लिए उपयोग करना चाहते हैं (2 के बजाय 1 का उपयोग करें)
function ScriptPath() {
var scriptPath = '';
try {
//Throw an error to generate a stack trace
throw new Error();
}
catch(e) {
//Split the stack trace into each line
var stackLines = e.stack.split('\n');
var callerIndex = 0;
//Now walk though each line until we find a path reference
for(var i in stackLines){
if(!stackLines[i].match(/http[s]?:\/\//)) continue;
//We skipped all the lines with out an http so we now have a script reference
//This one is the class constructor, the next is the getScriptPath() call
//The one after that is the user code requesting the path info (so offset by 2)
callerIndex = Number(i) + 2;
break;
}
//Now parse the string for each section we want to return
pathParts = stackLines[callerIndex].match(/((http[s]?:\/\/.+\/)([^\/]+\.js)):/);
}
this.fullPath = function() {
return pathParts[1];
};
this.path = function() {
return pathParts[2];
};
this.file = function() {
return pathParts[3];
};
this.fileNoExt = function() {
var parts = this.file().split('.');
parts.length = parts.length != 1 ? parts.length - 1 : 1;
return parts.join('.');
};
}
function a(){ function b(){ function c(){ return ScriptPath(); } return c(); } return b(); } a()
कंसोल में मेरे साथ काम नहीं करता है (एक फ़ाइल में कोशिश नहीं की गई है), लेकिन एक उचित विचार है। दृश्यता के लिए वैसे भी उत्कीर्ण होना चाहिए।
बस कंसोल अपनी त्रुटि स्टैक लॉग करें। तब आप जान सकते हैं कि आपको कैसे बुलाया जा रहा है
const hello = () => {
console.log(new Error('I was called').stack)
}
const sello = () => {
hello()
}
sello()
caller
सख्त मोड में निषिद्ध है । यहाँ (गैर-मानक) Error
स्टैक का उपयोग करके एक विकल्प है ।
निम्न कार्य फ़ायरफ़ॉक्स 52 और क्रोम 61-71 में काम करता प्रतीत होता है, हालांकि इसके कार्यान्वयन से दो ब्राउज़रों के लॉगिंग प्रारूप के बारे में बहुत सारी धारणाएँ बन जाती हैं और सावधानी के साथ इसका उपयोग किया जाना चाहिए, यह देखते हुए कि यह एक अपवाद फेंकता है और संभवतः दो regex निष्पादित करता है। मैच होने से पहले।
'use strict';
const fnNameMatcher = /([^(]+)@|at ([^(]+) \(/;
function fnName(str) {
const regexResult = fnNameMatcher.exec(str);
return regexResult[1] || regexResult[2];
}
function log(...messages) {
const logLines = (new Error().stack).split('\n');
const callerName = fnName(logLines[1]);
if (callerName !== null) {
if (callerName !== 'log') {
console.log(callerName, 'called log with:', ...messages);
} else {
console.log(fnName(logLines[2]), 'called log with:', ...messages);
}
} else {
console.log(...messages);
}
}
function foo() {
log('hi', 'there');
}
(function main() {
foo();
}());
ईएस 6 और सख्त मोड दोनों में, कॉलर फ़ंक्शन प्राप्त करने के लिए निम्नलिखित का उपयोग करें
console.log((new Error()).stack.split("\n")[2].trim().split(" ")[1])
कृपया ध्यान दें कि, यदि कोई कॉलर या कोई पिछला स्टैक नहीं है, तो उपरोक्त लाइन एक अपवाद को फेंक देगी। तदनुसार उपयोग करें।
console.log((new Error()).stack.split("\n")[1].trim().split(" ")[1])
मैं इसके लिए अपनी फिडेल यहाँ जोड़ना चाहता था:
http://jsfiddle.net/bladnman/EhUm3/
मैंने परीक्षण किया कि यह क्रोम, सफारी और IE (10 और 8) है। ठीक काम करता है। केवल 1 फ़ंक्शन होता है जो मायने रखता है, इसलिए यदि आप बड़ी बेला से डरते हैं, तो नीचे पढ़ें।
नोट: इस फिडेल में मेरी अपनी "बॉयलरप्लेट" की उचित मात्रा है। आप उस सब को हटा सकते हैं और यदि आप चाहें तो विभाजन का उपयोग कर सकते हैं। यह सिर्फ एक अति-सुरक्षित "फ़ंक्शंस का सेट है जिस पर मुझे भरोसा करना है।
वहाँ भी एक "JSFiddle" टेम्पलेट है कि मैं कई fiddles के लिए बस जल्दी fiddling का उपयोग करें।
String.prototype.trim = trim;
यदि आप केवल फ़ंक्शन नाम चाहते हैं और कोड नहीं, और ब्राउज़र-स्वतंत्र समाधान चाहते हैं, तो निम्न का उपयोग करें:
var callerFunction = arguments.callee.caller.toString().match(/function ([^\(]+)/)[1];
ध्यान दें कि यदि कोई कॉलर फ़ंक्शन नहीं है, तो ऊपर एक त्रुटि वापस आ जाएगी क्योंकि सरणी में कोई [1] तत्व नहीं है। चारों ओर काम करने के लिए, नीचे का उपयोग करें:
var callerFunction = (arguments.callee.caller.toString().match(/function ([^\(]+)/) === null) ? 'Document Object Model': arguments.callee.caller.toString().match(/function ([^\(]+)/)[1], arguments.callee.toString().match(/function ([^\(]+)/)[1]);
बस आपको यह बता देना चाहता हूं कि PhoneGap / Android पर name
काम नहीं कर रहा है। लेकिन arguments.callee.caller.toString()
चाल चलेगा।
यहाँ, सब कुछ लेकिन RegExp के साथ functionname
छीन लिया गया है caller.toString()
।
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Show the callers name</title><!-- This validates as html5! -->
<script>
main();
function main() { Hello(); }
function Hello(){
var name = Hello.caller.toString().replace(/\s\([^#]+$|^[^\s]+\s/g,'');
name = name.replace(/\s/g,'');
if ( typeof window[name] !== 'function' )
alert ("sorry, the type of "+name+" is "+ typeof window[name]);
else
alert ("The name of the "+typeof window[name]+" that called is "+name);
}
</script>
यहाँ पूर्ण स्टैकट्रेस पाने के लिए एक समारोह है :
function stacktrace() {
var f = stacktrace;
var stack = 'Stack trace:';
while (f) {
stack += '\n' + f.name;
f = f.caller;
}
return stack;
}
heystewart का उत्तर और JiarongWu के उत्तर दोनों ने उल्लेख किया कि Error
वस्तु की पहुंच है stack
।
यहाँ एक उदाहरण है:
function main() {
Hello();
}
function Hello() {
var stack;
try {
throw new Error();
} catch (e) {
stack = e.stack;
}
// N.B. stack === "Error\n at Hello ...\n at main ... \n...."
var m = stack.match(/.*?Hello.*?\n(.*?)\n/);
if (m) {
var caller_name = m[1];
console.log("Caller is:", caller_name)
}
}
main();
विभिन्न ब्राउज़र विभिन्न स्ट्रिंग स्वरूपों में स्टैक को दिखाते हैं:
Safari : Caller is: main@https://stacksnippets.net/js:14:8
Firefox : Caller is: main@https://stacksnippets.net/js:14:3
Chrome : Caller is: at main (https://stacksnippets.net/js:14:3)
IE Edge : Caller is: at main (https://stacksnippets.net/js:14:3)
IE : Caller is: at main (https://stacksnippets.net/js:14:3)
अधिकांश ब्राउज़र स्टैक को सेट करेंगे var stack = (new Error()).stack
। इंटरनेट एक्सप्लोरर में स्टैक अपरिभाषित होगा - स्टैक को पुनः प्राप्त करने के लिए आपको एक वास्तविक अपवाद फेंकना होगा।
निष्कर्ष: यह निर्धारित करना संभव है कि "मुख्य" ऑब्जेक्ट stack
में उपयोग करके "हैलो" का कॉलर है Error
। वास्तव में यह उन मामलों में काम करेगा जहां callee
/ caller
दृष्टिकोण काम नहीं करता है। यह आपको संदर्भ, स्रोत फ़ाइल और लाइन नंबर भी दिखाएगा। हालाँकि समाधान क्रॉस प्लेटफॉर्म बनाने के लिए प्रयास आवश्यक है।
ध्यान दें कि आप Node.js में Function.caller का उपयोग नहीं कर सकते , इसके बजाय कॉलर-आईडी पैकेज का उपयोग करें। उदाहरण के लिए:
var callerId = require('caller-id');
function foo() {
bar();
}
function bar() {
var caller = callerId.getData();
/*
caller = {
typeName: 'Object',
functionName: 'foo',
filePath: '/path/of/this/file.js',
lineNumber: 5,
topLevelFlag: true,
nativeFlag: false,
evalFlag: false
}
*/
}
निम्नलिखित कोड आज़माएं:
function getStackTrace(){
var f = arguments.callee;
var ret = [];
var item = {};
var iter = 0;
while ( f = f.caller ){
// Initialize
item = {
name: f.name || null,
args: [], // Empty array = no arguments passed
callback: f
};
// Function arguments
if ( f.arguments ){
for ( iter = 0; iter<f.arguments.length; iter++ ){
item.args[iter] = f.arguments[iter];
}
} else {
item.args = null; // null = argument listing not supported
}
ret.push( item );
}
return ret;
}
फ़ायरफ़ॉक्स -21 और क्रोमियम -25 में मेरे लिए काम किया।
arguments.callee
कई वर्षों के लिए पदावनत कर दिया गया है ।
इस समस्या के आसपास एक और तरीका यह है कि कॉलिंग फ़ंक्शन का नाम एक पैरामीटर के रूप में दिया जाए।
उदाहरण के लिए:
function reformatString(string, callerName) {
if (callerName === "uid") {
string = string.toUpperCase();
}
return string;
}
अब, आप फ़ंक्शन को इस तरह से कॉल कर सकते हैं:
function uid(){
var myString = "apples";
reformatString(myString, function.name);
}
मेरा उदाहरण फ़ंक्शन नाम के हार्ड कोडित चेक का उपयोग करता है, लेकिन आप आसानी से एक स्विच स्टेटमेंट या कुछ अन्य लॉजिक का उपयोग कर सकते हैं।
जहां तक मुझे पता है, हमारे पास इसके लिए 2 तरीके हैं जैसे कि दिए गए स्रोतों से-
function whoCalled()
{
if (arguments.caller == null)
console.log('I was called from the global scope.');
else
console.log(arguments.caller + ' called me!');
}
function myFunc()
{
if (myFunc.caller == null) {
return 'The function was called from the top!';
}
else
{
return 'This function\'s caller was ' + myFunc.caller;
}
}
सोचो यू तुम्हारा जवाब है :)।
क्यों उपरोक्त सभी समाधान एक रॉकेट विज्ञान की तरह दिखते हैं। इस बीच, यह इस स्निपेट से अधिक जटिल नहीं होना चाहिए। सारा श्रेय इस लड़के को जाता है
आप जावास्क्रिप्ट में कॉलर फ़ंक्शन का पता कैसे लगाते हैं?
var stackTrace = function() {
var calls = [];
var caller = arguments.callee.caller;
for (var k = 0; k < 10; k++) {
if (caller) {
calls.push(caller);
caller = caller.caller;
}
}
return calls;
};
// when I call this inside specific method I see list of references to source method, obviously, I can add toString() to each call to see only function's content
// [function(), function(data), function(res), function(l), function(a, c), x(a, b, c, d), function(c, e)]
मैं इस प्रश्न के साथ प्रश्न और वर्तमान दोनों को संबोधित करने का प्रयास कर रहा हूं।
बाउंटी के लिए आवश्यक है कि कॉलर को सख्त मोड में प्राप्त किया जाए , और जिस तरह से मैं इसे देख सकता हूं वह केवल एक फ़ंक्शन को बाहर की ओर संदर्भित करके है सख्त मोड के है।
उदाहरण के लिए, निम्नलिखित गैर-मानक है लेकिन क्रोम, एज और फ़ायरफ़ॉक्स के पिछले (29/03/2016) और वर्तमान (1 अगस्त 2018) संस्करणों के साथ परीक्षण किया गया है।
function caller()
{
return caller.caller.caller;
}
'use strict';
function main()
{
// Original question:
Hello();
// Bounty question:
(function() { console.log('Anonymous function called by ' + caller().name); })();
}
function Hello()
{
// How do you find out the caller function is 'main'?
console.log('Hello called by ' + caller().name);
}
main();
यदि आपको वास्तव में किसी कारण से कार्यक्षमता की आवश्यकता है और चाहते हैं कि यह क्रॉस-ब्राउज़र संगत हो और सख्त सामान की चिंता न करें और आगे संगत रहें तो इस संदर्भ को पास करें:
function main()
{
Hello(this);
}
function Hello(caller)
{
// caller will be the object that called Hello. boom like that...
// you can add an undefined check code if the function Hello
// will be called without parameters from somewhere else
}
मुझे लगता है कि निम्नलिखित कोड टुकड़ा मददगार हो सकता है:
window.fnPureLog = function(sStatement, anyVariable) {
if (arguments.length < 1) {
throw new Error('Arguments sStatement and anyVariable are expected');
}
if (typeof sStatement !== 'string') {
throw new Error('The type of sStatement is not match, please use string');
}
var oCallStackTrack = new Error();
console.log(oCallStackTrack.stack.replace('Error', 'Call Stack:'), '\n' + sStatement + ':', anyVariable);
}
कोड निष्पादित करें:
window.fnPureLog = function(sStatement, anyVariable) {
if (arguments.length < 1) {
throw new Error('Arguments sStatement and anyVariable are expected');
}
if (typeof sStatement !== 'string') {
throw new Error('The type of sStatement is not match, please use string');
}
var oCallStackTrack = new Error();
console.log(oCallStackTrack.stack.replace('Error', 'Call Stack:'), '\n' + sStatement + ':', anyVariable);
}
function fnBsnCallStack1() {
fnPureLog('Stock Count', 100)
}
function fnBsnCallStack2() {
fnBsnCallStack1()
}
fnBsnCallStack2();
लॉग इस तरह दिखता है:
Call Stack:
at window.fnPureLog (<anonymous>:8:27)
at fnBsnCallStack1 (<anonymous>:13:5)
at fnBsnCallStack2 (<anonymous>:17:5)
at <anonymous>:20:1
Stock Count: 100