texto que negrita letra ejemplos descargar definicion javascript callstack

negrita - ¿Cómo se encuentra la función de la persona que llama en JavaScript?



que es javascript (29)

StackTrace

Puede encontrar todo el seguimiento de la pila utilizando el código específico del navegador. Lo bueno es que alguien ya lo hizo ; Aquí está el código del proyecto en GitHub .

Pero no todas las noticias son buenas:

  1. Es realmente lento obtener el seguimiento de la pila, así que ten cuidado (lee this para más información).

  2. Deberá definir los nombres de las funciones para que la traza de la pila sea legible. Porque si tienes código como este:

    var Klass = function kls() { this.Hello = function() { alert(printStackTrace().join(''/n/n'')); }; } new Klass().Hello();

    Google Chrome alertará ... kls.Hello ( ... pero la mayoría de los navegadores esperarán un nombre de función justo después de la function palabra clave y lo tratarán como una función anónima. Ni siquiera Chrome podrá usar el nombre de Klass si usted No le des el nombre kls a la función.

    Y, por cierto, puede pasar a la función printStackTrace la opción {guess: true} pero no encontré ninguna mejora real al hacer eso.

  3. No todos los navegadores te dan la misma información. Es decir, parámetros, columna de código, etc.

Nombre de la función del llamante

Por cierto, si solo quieres el nombre de la función de la persona que llama (en la mayoría de los navegadores, pero no de IE) puedes usar:

arguments.callee.caller.name

Pero tenga en cuenta que este nombre será el siguiente a la palabra clave de function . No encontré la forma (incluso en Google Chrome) de obtener más que eso sin obtener el código de toda la función.

Código de función del llamante

Y resumiendo el resto de las mejores respuestas (por Pablo Cabrera, nourdine y Greg Hewgill). El único navegador cruzado y lo realmente seguro que puedes usar es:

arguments.callee.caller.toString();

El cual mostrará el código de la función del que llama. Lamentablemente, eso no es suficiente para mí, y es por eso que te doy consejos para el StackTrace y el nombre de la función de la persona que llama (aunque no son de navegador cruzado).

function main() { Hello(); } function Hello() { // How do you find out the caller function is ''main''? }

¿Hay alguna manera de averiguar la pila de llamadas en absoluto?


Aquí hay una función para Function.caller :

function stacktrace() { var f = stacktrace; var stack = ''Stack trace:''; while (f) { stack += ''/n'' + f.name; f = f.caller; } return stack; }


Aquí, todo excepto el nombre de la functionname se caller.toString() de caller.toString() , con RegExp.

<!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>


Como ninguna de las respuestas anteriores funciona como lo que estaba buscando (obteniendo solo la última función del llamador, no una función como cadena o pila de llamadas), publico mi solución aquí para aquellos que son como yo y espero que esto funcione para el tema:

function getCallerName(func) { if (!func) return "anonymous"; let caller = func.caller; if (!caller) return "anonymous"; caller = caller.toString(); if (!caller.trim().startsWith("function")) return "anonymous"; return caller.substring(0, caller.indexOf("(")).replace("function",""); } // Example of how to use "getCallerName" function function Hello(){ console.log("ex1 => " + getCallerName(Hello)); } function Main(){ Hello(); // another example console.log("ex3 => " + getCallerName(Main)); } Main();


Creo que la siguiente pieza de código puede ser útil:

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

Ejecuta el código:

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();

El registro se ve así:

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


Es más seguro usar *arguments.callee.caller ya que los arguments.caller están en desuso ...


Estoy tratando de abordar tanto la pregunta como la recompensa actual con esta pregunta.

La recompensa requiere que la persona que llama se obtenga en modo estricto , y la única forma en que puedo ver esto es haciendo referencia a una función declarada fuera del modo estricto.

Por ejemplo, lo siguiente no es estándar pero se ha probado con versiones anteriores (29/03/2016) y actuales (1 de agosto de 2018) de Chrome, Edge y Firefox.

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();


Intenta acceder a esto:

arguments.callee.caller.name


Normalmente uso (new Error()).stack en Chrome. Lo bueno es que esto también le da los números de línea donde la persona que llama llamó a la función. La desventaja es que limita la longitud de la pila a 10, por lo que llegué a esta página en primer lugar.

(Estoy usando esto para recopilar acumulaciones de llamadas en un constructor de bajo nivel durante la ejecución, para ver y depurar más tarde, por lo que establecer un punto de interrupción no es de utilidad ya que será alcanzado miles de veces)


Otra forma de solucionar este problema es simplemente pasar el nombre de la función de llamada como parámetro.

Por ejemplo:

function reformatString(string, callerName) { if (callerName === "uid") { string = string.toUpperCase(); } return string; }

Ahora, podrías llamar a la función así:

function uid(){ var myString = "apples"; reformatString(myString, function.name); }

Mi ejemplo utiliza una verificación codificada del nombre de la función, pero podría usar fácilmente una instrucción switch o alguna otra lógica para hacer lo que quiera.


Para recapitular (y hacerlo más claro) ...

este código:

function Hello() { alert("caller is " + arguments.callee.caller.toString()); }

es equivalente a esto:

function Hello() { alert("caller is " + Hello.caller.toString()); }

Claramente, el primer bit es más portátil, ya que puede cambiar el nombre de la función, digamos desde "Hola" a "Ciao", y aún así hacer que todo funcione.

En este último caso, en caso de que decida refactorizar el nombre de la función invocada (Hola), tendría que cambiar todas sus apariciones :(


Parece que esta es una pregunta bastante resuelta, pero recientemente descubrí que la developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… por lo que para mi propio uso escribí una clase que obtendrá la ruta desde donde se llama. Es parte de una pequeña libreta auxiliar y, si desea usar el código independiente, cambie el desplazamiento utilizado para devolver el seguimiento de pila de la persona que llama (use 1 en lugar de 2)

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(''.''); }; }


Por lo que sé, tenemos dos formas para esto de fuentes dadas como esta:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller

    function whoCalled() { if (arguments.caller == null) console.log(''I was called from the global scope.''); else console.log(arguments.caller + '' called me!''); }

  2. Function.caller

    function myFunc() { if (myFunc.caller == null) { return ''The function was called from the top!''; } else { return ''This function/'s caller was '' + myFunc.caller; } }

Creo que tienes tu respuesta :).


Por qué todas las soluciones anteriores parecen una ciencia espacial. Mientras tanto, no debería ser más complicado que este fragmento. Todos los créditos a este chico

¿Cómo se encuentra la función de la persona que llama en JavaScript?

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)]


Prueba el siguiente código:

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

Me funcionó en Firefox-21 y Chromium-25.


Puede usar Function.Caller para obtener la función de llamada. El método antiguo que usa argument.caller se considera obsoleto.

El siguiente código ilustra su uso:

function Hello() { return Hello.caller;} Hello2 = function NamedFunc() { return NamedFunc.caller; }; function main() { Hello(); //both return main() Hello2(); }

Notas sobre el argumento.caller obsoleto: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller

Tenga en cuenta que Function.caller no es estándar: Function.caller


Puedes conseguir el stacktrace completo:

arguments.callee.caller arguments.callee.caller.caller arguments.callee.caller.caller.caller

Hasta que la persona que llama es null .

Nota: causa un bucle infinito en funciones recursivas.


Quería agregar mi violín aquí para esto:

http://jsfiddle.net/bladnman/EhUm3/

He probado que esto es Chrome, Safari y IE (10 y 8). Funciona bien. Solo hay una función que importa, por lo que si te asusta el gran violín, lee a continuación.

Nota: Hay una buena cantidad de mi "placa de calderas" en este violín. Puedes eliminar todo eso y usar split''s si quieres. Es solo un conjunto de funciones "ultra-seguras" en las que he llegado a confiar.

También hay una plantilla "JSFiddle" allí que uso para muchos violines simplemente para tocar el violín.


Sé que mencionó "en Javascript", pero si el propósito es la depuración, creo que es más fácil usar las herramientas de desarrollo de su navegador. Así es como se ve en Chrome: Simplemente suelta el depurador donde quieras investigar la pila.


Si no lo va a ejecutar en IE <11, entonces le convendría con console.trace() .

function main() { Hello(); } function Hello() { console.trace() } main() // Hello @ VM261:9 // main @ VM261:4


Si realmente necesita la funcionalidad por algún motivo y desea que sea compatible con todos los navegadores y no se preocupe por las cosas estrictas y que sea compatible con el futuro, pase esta referencia:

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 }


Si solo desea el nombre de la función y no el código, y desea una solución independiente del navegador, use lo siguiente:

var callerFunction = arguments.callee.caller.toString().match(/function ([^/(]+)/)[1];

Tenga en cuenta que lo anterior devolverá un error si no hay una función de llamada, ya que no hay ningún elemento [1] en la matriz. Para solucionar el problema, use lo siguiente:

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]);


Simplemente consola de registro de su pila de errores. Entonces puedes saber cómo estás siendo llamado

const hello = () => { console.log(new Error(''I was called'').stack) } const sello = () => { hello() } sello()


Solo quiero hacerle saber que en PhoneGap / Android el name no parece estar funcionando. Pero arguments.callee.caller.toString() hará el truco.


Un mensaje de 2018 donde está prohibido acceder a la caller que caller :

La siguiente función parece hacer el trabajo en Firefox 52 y Chrome 61, aunque su implementación hace muchas suposiciones sobre el formato de registro de los dos navegadores y no debe usarse para la depuración temporal del desarrollador ya que produce una excepción y posiblemente ejecuta dos. Regex emparejamientos antes de ser hecho.

let fnNameMatcher = /([^(]+)@|at ([^(]+) /(/; function fnName(str) { let regexResult = fnNameMatcher.exec(str); return regexResult[1] || regexResult[2]; } export function log(...messages: any[]) { let logLines = (new Error().stack).split(''/n''); let callerName = fnName(logLines[1]); if (callerName !== null) { if (callerName !== ''log'') { console.log(callerName, ...messages); } else { console.log(fnName(logLines[2]), ...messages); } } else { console.log(...messages); } }


Yo haría esto:

function Hello() { console.trace(); }


La respuesta de heystewart y la respuesta de JiarongWu mencionaron que el objeto Error tiene acceso a la stack .

Aquí hay un ejemplo:

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();

Diferentes navegadores muestran la pila en diferentes formatos de cadena:

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)

La mayoría de los navegadores configurarán la pila con var stack = (new Error()).stack . En Internet Explorer, la pila estará indefinida; debe lanzar una excepción real para recuperar la pila.

Conclusión: es posible determinar que "principal" es la persona que llama a "Hola" usando la stack en el objeto Error . De hecho, funcionará en los casos en que el enfoque de la caller que caller / caller que caller no funciona. También le mostrará el contexto, es decir, el archivo fuente y el número de línea. Sin embargo, se requiere un esfuerzo para hacer que la solución sea multiplataforma.


function Hello() { alert("caller is " + Hello.caller); }

Tenga en cuenta que esta función no es estándar , de Function.caller :

No estándar
Esta característica no es estándar y no está en una pista estándar. No lo use en sitios de producción orientados a la Web: no funcionará para todos los usuarios. También puede haber grandes incompatibilidades entre las implementaciones y el comportamiento puede cambiar en el futuro.

La siguiente es la respuesta anterior de 2008, que ya no se admite en Javascript moderno:

function Hello() { alert("caller is " + arguments.callee.caller.toString()); }


function Hello() { alert(Hello.caller); }