Comment découvrir la fonction appelant en JavaScript?

866
function main()
{
   Hello();
}

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

Existe-t-il un moyen de découvrir la pile d'appels?

Ray Lu
la source
63
J'espère que c'est juste pour vous aider dans le débogage. Un comportement différent en fonction de l'appelant est une mauvaise idée.
JO.
Quand cela serait-il utile pour le débogage?
Anderson Green
33
@AndersonGreen lorsque vous avez, par exemple, une méthode de rendu de modèle par défaut et voyez qu'elle est appelée deux fois. Plutôt que de passer au peigne fin des milliers de LoC ou de passer au travers du débogueur, vous pouvez simplement voir quelle était la pile à l'époque.
tkone
28
pour voir la trace de la pile, utilisez console.trace () pour chrome. je ne sais pas pour les autres cependant
lukas.pukenis
5
pourquoi est-ce une mauvaise idee?
Jacob Schneider

Réponses:

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

Notez que cette fonctionnalité n'est pas standard , à partir de Function.caller:

Non standard
Cette fonctionnalité n'est pas standard et n'est pas sur une piste standard. Ne l'utilisez pas sur des sites de production face au Web: cela ne fonctionnera pas pour tous les utilisateurs. Il peut également y avoir de grandes incompatibilités entre les implémentations et le comportement peut changer à l'avenir.


Voici l'ancienne réponse de 2008, qui n'est plus prise en charge dans Javascript moderne:

function Hello()
{
    alert("caller is " + arguments.callee.caller.toString());
}
Greg Hewgill
la source
254
arguments.callee.caller.nameobtiendra le nom de la fonction.
Rocket Hazmat
137
"Les propriétés 'caller', 'callee' et 'arguments' ne sont pas accessibles sur les fonctions en mode strict ou les objets arguments pour les appeler" - elles sont obsolètes dans ES5 et supprimées en mode strict.
ThatGuy
12
Cela ne fonctionnera que si vous n'utilisez pas le mode strict. La suppression 'use strict';pourrait donc être utile.
pvorb
23
argumentsPEUT être accessible à partir d'une fonction en mode strict, il serait stupide de le déprécier. tout simplement pas de function.arguments de l'extérieur. De plus, si vous avez un argument nommé, sa forme arguments [i] ne suivra pas les modifications que vous apportez à la version nommée dans la fonction.
rvr_jon
41
Cette méthode est devenue obsolète depuis que cet article a été répertorié en 2011. La méthode préférée est désormais Function.caller, (à partir de 2015).
Greg
152

Trace de la pile

Vous pouvez trouver l'intégralité de la trace de la pile à l'aide d'un code spécifique au navigateur. La bonne chose est que quelqu'un l'a déjà fait ; voici le code du projet sur GitHub .

Mais toutes les nouvelles ne sont pas bonnes:

  1. Il est très lent d'obtenir la trace de la pile, alors soyez prudent (lisez ceci pour en savoir plus).

  2. Vous devrez définir des noms de fonction pour que la trace de pile soit lisible. Parce que si vous avez un code comme celui-ci:

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

    Google Chrome alertera ... kls.Hello ( ...mais la plupart des navigateurs s'attendront à un nom de fonction juste après le mot-clé functionet le traiteront comme une fonction anonyme. Un même Chrome ne pourra pas utiliser le Klassnom si vous ne donnez pas le nom klsà la fonction.

    Et au fait, vous pouvez passer à la fonction printStackTrace l'option {guess: true}mais je n'ai trouvé aucune amélioration réelle en faisant cela.

  3. Tous les navigateurs ne vous donnent pas les mêmes informations. Autrement dit, les paramètres, la colonne de code, etc.


Nom de la fonction de l'appelant

Soit dit en passant, si vous ne voulez que le nom de la fonction appelant (dans la plupart des navigateurs, mais pas IE), vous pouvez utiliser:

arguments.callee.caller.name

Mais notez que ce nom sera celui après le functionmot - clé. Je n'ai trouvé aucun moyen (même sur Google Chrome) d'obtenir plus que cela sans obtenir le code de la fonction entière.


Code de fonction de l'appelant

Et résumant le reste des meilleures réponses (par Pablo Cabrera, nourdine et Greg Hewgill). La seule chose multi-navigateur et vraiment sûre que vous pouvez utiliser est:

arguments.callee.caller.toString();

Qui affichera le code de la fonction appelant. Malheureusement, cela ne me suffit pas, et c'est pourquoi je vous donne des conseils pour le StackTrace et le nom de la fonction d'appel (bien qu'ils ne soient pas multi-navigateurs).

Mariano Desanze
la source
1
vous devriez peut-être ajouter Function.callerselon la réponse de @ Greg
Zach Lysobey
Function.callerne fonctionnera pas en mode strict, cependant.
Rickard Elimää
54

Je sais que vous avez mentionné "en Javascript", mais si le but est le débogage, je pense qu'il est plus facile d'utiliser simplement les outils de développement de votre navigateur. Voici à quoi cela ressemble dans Chrome: entrez la description de l'image ici déposez simplement le débogueur à l'endroit où vous souhaitez enquêter sur la pile.

Phil
la source
3
C'est une vieille question ... mais c'est certainement la façon la plus moderne de le faire aujourd'hui.
markstewie
53

Pour récapituler (et le rendre plus clair) ...

ce code:

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

est équivalent à ceci:

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

De toute évidence, le premier bit est plus portable, car vous pouvez changer le nom de la fonction, par exemple de "Bonjour" à "Ciao", et toujours faire fonctionner le tout.

Dans ce dernier cas, si vous décidez de refactoriser le nom de la fonction invoquée (Bonjour), vous devrez modifier toutes ses occurrences :(

nourdine
la source
7
arguments.callee.caller toujours null sur Chrome 25.0.1364.5 dev
Kokizzu
53

Vous pouvez obtenir la trace de pile complète:

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

Jusqu'à ce que l'appelant soit null.

Remarque: cela provoque une boucle infinie sur les fonctions récursives.

ale5000
la source
2
Désolé pour la réponse tardive, mais je n'ai jamais vu votre commentaire auparavant; seulement pour le cas de récursivité, cela ne fonctionne pas, dans d'autres cas, cela devrait fonctionner.
ale5000
45

J'utilise habituellement (new Error()).stack dans Chrome. La bonne chose est que cela vous donne également les numéros de ligne où l'appelant a appelé la fonction. L'inconvénient est qu'il limite la longueur de la pile à 10, c'est pourquoi je suis venu sur cette page en premier lieu.

(J'utilise cela pour collecter des piles d'appels dans un constructeur de bas niveau pendant l'exécution, pour afficher et déboguer plus tard, donc la définition d'un point d'arrêt n'est pas utile car il sera atteint des milliers de fois)

heystewart
la source
Pourriez-vous s'il vous plaît ajouter un peu plus de description sur l'explication que vous fournissez?
abarisone
6
C'est la seule chose que je pouvais faire au travail une fois 'use strict';en place. M'a donné les informations dont j'avais besoin - merci!
Jeremy Harris
5
Concernant la limite de longueur de pile ... vous pouvez changer cela avec "Error.stackTraceLimit = Infinity".
Tom
(nouvelle erreur ("StackLog")). stack.split ("\ n") rend la lecture plus agréable.
Teoman shipahi
36

Si vous n'allez pas l'exécuter dans IE <11, alors console.trace () conviendrait.

function main() {
    Hello();
}

function Hello() {
    console.trace()
}

main()
// Hello @ VM261:9
// main @ VM261:4
gumkins
la source
Ça marche! Devrait être ajouté plus de votes
positifs
22

Vous pouvez utiliser Function.Caller pour obtenir la fonction appelante. L'ancienne méthode utilisant argument.caller est considérée comme obsolète.

Le code suivant illustre son utilisation:

function Hello() { return Hello.caller;}

Hello2 = function NamedFunc() { return NamedFunc.caller; };

function main()
{
   Hello();  //both return main()
   Hello2();
}

Notes sur l'argument.caller obsolète: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller

Soyez conscient que Function.caller n'est pas standard: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller

Greg
la source
1
C'est la bonne réponse de nos jours. Vous ne pouvez plus faire de trucs arguments.caller.callee. Je souhaite que nous puissions faire passer cela au sommet, car toutes les autres choses sont obsolètes maintenant.
coblr
4
Semble que ce n'est pas possible en mode strict? Cannot access caller property of a strict mode function
Zach Lysobey
Function.caller ne fonctionnait pas non plus pour moi en mode strict. De plus, selon MDN , function.caller n'est pas standard et ne doit pas être utilisé en production. Cela pourrait fonctionner pour le débogage, cependant.
jkdev
Je n'ai eu aucun problème avec le non standard s'il fonctionnait dans Node, mais ce n'est tout simplement pas autorisé en mode strict (j'ai testé sur le nœud 6.10). Il en va de même pour les «arguments». Je reçois un message d'erreur: '' 'appelant' et 'arguments' sont des propriétés de fonction restreintes et ne sont pas accessibles dans ce contexte. "
Tom
21

Je ferais ceci:

function Hello() {
  console.trace();
}
inorganik
la source
Cela fonctionne très bien! devrait être accepté comme la bonne réponse, car d'autres méthodes sont anciennes \ ne fonctionnent plus
Yuval Pruss
19
function Hello() {
    alert(Hello.caller);
}
Shadow2531
la source
1
Et juste pour le nom de la fonction, utilisez Hello.caller.name
vanval
même quearguments.callee.caller.toString()
user2720864
Cela devrait être la bonne réponse, au moins pour 2016
Daniel
Ce n'est pas sur une voie normative, mais cela fonctionnera à partir d'ECMAScript 5.
Obinna Nwakwue
1
@Daniel: non, ça ne devrait pas. Voir developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Dan Dascalescu
18

Il est plus sûr à utiliser *arguments.callee.callercar il arguments.callerest obsolète ...

Pablo Cabrera
la source
36
arguments.calleeest également déconseillé dans ES5 et supprimé en mode strict.
nyuszika7h
2
Y a-t-il une alternative? Edit: arguments.calleeétait une mauvaise solution à un problème qui a maintenant été mieux résolu developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Matthew
16

On dirait que c'est une question assez résolue, mais j'ai récemment découvert que l' appelé n'est pas autorisé en «mode strict», donc pour mon propre usage, j'ai écrit une classe qui obtiendra le chemin d'où elle s'appelle. Cela fait partie d'une petite bibliothèque d'aide et si vous souhaitez utiliser le code de manière autonome, changez l'offset utilisé pour renvoyer la trace de pile de l'appelant (utilisez 1 au lieu 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('.');
  };
}
QueueHammer
la source
Ne fonctionne pas pour moi avec function a(){ function b(){ function c(){ return ScriptPath(); } return c(); } return b(); } a()dans la console (je n'ai pas essayé dans un fichier), mais semble avoir une idée raisonnable. Doit être voté de toute façon pour la visibilité.
ninjagecko
L'idée est géniale. J'analyse différemment mais dans les applications nw.js, c'est vraiment la seule idée qui donne ce que je cherche.
Andrew Grothe
Veuillez fournir un exemple de la façon d'appeler cette fonction.
pd_au
11

Consignez simplement votre console dans la pile des erreurs. Vous pouvez alors savoir comment vous appelez

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

const sello = () => {
  hello()
}

sello()

Prasanna
la source
10

En mode ES6 et strict, utilisez ce qui suit pour obtenir la fonction Appelant

console.log((new Error()).stack.split("\n")[2].trim().split(" ")[1])

Veuillez noter que la ligne ci-dessus lèvera une exception s'il n'y a aucun appelant ou aucune pile précédente. Utilisez en conséquence.

VanagaS
la source
Pour obtenir l'appel (le nom de la fonction actuelle), utilisez: console.log((new Error()).stack.split("\n")[1].trim().split(" ")[1])
VanagaS
10

Mise à jour 2018

callerest interdit en mode strict . Voici une alternative utilisant la pile (non standard)Error .

La fonction suivante semble faire le travail dans Firefox 52 et Chrome 61-71 bien que son implémentation fasse beaucoup d'hypothèses sur le format de journalisation des deux navigateurs et doit être utilisée avec prudence, car elle lève une exception et exécute éventuellement deux expressions régulières appariements avant d'être fait.

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

Rovanion
la source
4
C'est incroyable et aussi horrible.
Ian
J'ai reçu "foo appelé avec: hi there", mais foo n'a pas été appelé avec "hi there", le journal a été appelé avec "hi there"
AndrewR
À droite, il y avait un "modificateur mal placé" dans la grammaire du message d'erreur. Cela voulait dire "log a été appelé à partir de la fonction f, il voulait que le message X soit imprimé" mais de la manière la plus succincte possible.
Rovanion
7

Je voulais ajouter mon violon ici pour cela:

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

J'ai testé c'est chrome, safari et IE (10 et 8). Fonctionne bien. Il n'y a qu'une seule fonction qui compte, donc si vous avez peur du gros violon, lisez ci-dessous.

Remarque: il y a une bonne quantité de mon propre "passe-partout" dans ce violon. Vous pouvez supprimer tout cela et utiliser des scissions si vous le souhaitez. C'est juste un ensemble de fonctions ultra-sûres sur lesquelles je viens de compter.

Il y a aussi un modèle "JSFiddle" que j'utilise pour de nombreux violons pour un simple violon rapide.

bladnman
la source
Je me demande si vous pourriez ajouter les "helpers" comme extensions pour le prototype dans certains cas, par exemple:String.prototype.trim = trim;
autiste
6

Si vous souhaitez simplement le nom de la fonction et non le code, et souhaitez une solution indépendante du navigateur, utilisez ce qui suit:

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

Notez que ce qui précède retournera une erreur s'il n'y a pas de fonction d'appelant car il n'y a pas d'élément [1] dans le tableau. Pour contourner ce problème, utilisez ce qui suit:

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]);
JoolzCheat
la source
1
Cela est obsolète depuis de nombreuses années .
Dan Dascalescu
5

Je veux juste vous faire savoir que sur PhoneGap / Android du namedoesnt semblent fonctionner. Mais arguments.callee.caller.toString()fera l'affaire.

Pablo Armentano
la source
4

Ici, tout sauf le functionnameest supprimé caller.toString(), avec 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>
BrazFlat
la source
cela renvoie toujours la déclaration de méthode entière
Maslow
4

voici une fonction pour obtenir le stacktrace complet :

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

la source
3

La réponse de heystewart et la réponse de JiarongWu ont toutes deux mentionné que l' Errorobjet a accès à la stack.

Voici un exemple:

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

Différents navigateurs affichent la pile dans différents formats de chaîne:

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 plupart des navigateurs définiront la pile avec var stack = (new Error()).stack . Dans Internet Explorer, la pile ne sera pas définie - vous devez lever une véritable exception pour récupérer la pile.

Conclusion: Il est possible de déterminer "principal" est l'appelant à "Bonjour" en utilisant le stackdans l' Errorobjet. En fait, cela fonctionnera dans les cas où l' approche callee/ callerne fonctionne pas. Il vous montrera également le contexte, c'est-à-dire le fichier source et le numéro de ligne. Cependant, des efforts sont nécessaires pour rendre la solution multiplateforme.

Stephen Quan
la source
2

Notez que vous ne pouvez pas utiliser Function.caller dans Node.js, utilisez plutôt le package id-appelant . Par exemple:

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
    }
    */
}
ns16
la source
1

Essayez le code suivant:

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

A travaillé pour moi dans Firefox-21 et Chromium-25.

Diego Augusto Molina
la source
Essayez ceci pour les fonctions récursives.
daniel1426
arguments.calleeest obsolète depuis de nombreuses années .
Dan Dascalescu
1

Une autre façon de contourner ce problème consiste à simplement passer le nom de la fonction appelante en tant que paramètre.

Par exemple:

function reformatString(string, callerName) {

    if (callerName === "uid") {
        string = string.toUpperCase();
    }

    return string;
}

Maintenant, vous pouvez appeler la fonction comme ceci:

function uid(){
    var myString = "apples";

    reformatString(myString, function.name);
}

Mon exemple utilise une vérification codée en dur du nom de la fonction, mais vous pouvez facilement utiliser une instruction switch ou une autre logique pour faire ce que vous voulez.

GrayedFox
la source
Je crois que cela résout également les problèmes de compatibilité entre navigateurs, pour la plupart. Mais veuillez tester cela avant de supposer que c'est vrai! ( commence à transpirer )
GrayedFox
1

Pour autant que je sache, nous avons 2 voies pour cela à partir de sources données comme celle-ci-

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

Pensez que vous avez votre réponse :).

Abrar Jahin
la source
Cela est obsolète depuis de nombreuses années et Function.caller ne fonctionne pas en mode strict.
Dan Dascalescu
1

Pourquoi toutes les solutions ci-dessus ressemblent à une science de fusée. En attendant, cela ne devrait pas être plus compliqué que cet extrait. Tous les crédits à ce gars

Comment découvrir la fonction appelant 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)]
Anonyme
la source
3
Voici ce que j'obtiens en utilisant ceci: TypeError: les propriétés 'caller', 'callee' et 'arguments' ne sont pas accessibles sur les fonctions en mode strict ou les objets arguments pour les appeler. Des idées sur la façon de travailler cela en mode strict?
hard_working_ant
1

J'essaie de répondre à la fois à la question et à la prime actuelle avec cette question.

La prime nécessite que l'appelant soit obtenu en mode strict , et la seule façon dont je peux voir cela est de se référer à une fonction déclarée en dehors du mode strict.

Par exemple, ce qui suit n'est pas standard mais a été testé avec les versions précédentes (29/03/2016) et actuelles (1er août 2018) de Chrome, Edge et 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();

autistique
la source
Bon hack, mais ne fonctionnera pas pour les modules ES5, qui sont entièrement en mode strict .
Dan Dascalescu
0

Si vous avez vraiment besoin de la fonctionnalité pour une raison quelconque et que vous souhaitez qu'elle soit compatible avec tous les navigateurs et ne vous inquiétez pas pour les choses strictes et la compatibilité ascendante, passez une référence:

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
}
Mario PG
la source
0

Je pense que le morceau de code suivant peut être utile:

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

Exécutez le code:

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

Le journal ressemble à ceci:

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
JiarongWu
la source