Bagaimana Anda mengetahui fungsi pemanggil dalam JavaScript?

866
function main()
{
   Hello();
}

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

Apakah ada cara untuk mengetahui tumpukan panggilan?

Ray Lu
sumber
63
Saya harap ini hanya untuk membantu Anda dalam debugging. Memvariasikan perilaku berdasarkan penelepon adalah ide yang buruk.
OJ.
Kapan ini berguna untuk debugging?
Anderson Green
33
@AndersonGreen ketika Anda punya, misalnya, metode render templat default dan melihatnya dipanggil dua kali. Alih-alih menyisir 1000s LoC atau sulit melangkah dengan debugger, Anda bisa melihat apa tumpukan itu pada saat itu.
tkone
28
untuk melihat jejak tumpukan gunakan console.trace () untuk chrome. tidak tahu tentang orang lain
lukas.pukenis
5
Mengapa ini ide yang buruk?
Jacob Schneider

Jawaban:

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

Perhatikan bahwa fitur ini non-standar , dari Function.caller:

Non-standar
Fitur ini non-standar dan tidak pada jalur standar. Jangan menggunakannya di situs produksi yang menghadap Web: itu tidak akan berfungsi untuk setiap pengguna. Mungkin juga ada banyak ketidaksesuaian antara implementasi dan perilaku mungkin berubah di masa depan.


Berikut ini adalah jawaban lama dari 2008, yang tidak lagi didukung dalam Javascript modern:

function Hello()
{
    alert("caller is " + arguments.callee.caller.toString());
}
Greg Hewgill
sumber
254
arguments.callee.caller.nameakan mendapatkan nama fungsi.
Rocket Hazmat
137
"'penelepon', 'callee', dan 'argumen' properti mungkin tidak dapat diakses pada fungsi mode yang ketat atau objek argumen untuk panggilan ke mereka" - mereka ditinggalkan dalam ES5 dan dihapus dalam mode ketat.
ThatGuy
12
Ini hanya akan berfungsi, jika Anda tidak menggunakan mode ketat. Jadi menghapus 'use strict';mungkin membantu.
pvorb
23
argumentsBISA diakses dari dalam suatu fungsi dalam mode ketat, itu akan bodoh untuk mencabut itu. tidak hanya dari function.arguments dari luar. Juga, jika Anda memiliki argumen bernama, bentuk argumen [i] tidak akan melacak perubahan yang Anda buat ke versi bernama di dalam fungsi.
rvr_jon
41
Metode ini telah menjadi usang sejak posting ini terdaftar pada tahun 2011. Metode yang disukai sekarang adalah Function.caller, (per 2015).
Greg
152

StackTrace

Anda dapat menemukan seluruh jejak tumpukan menggunakan kode khusus browser. Hal yang baik adalah seseorang telah berhasil ; di sini adalah kode proyek di GitHub .

Namun tidak semua berita baik:

  1. Sangat lambat untuk mendapatkan jejak tumpukan jadi berhati-hatilah (baca ini lebih lanjut).

  2. Anda perlu mendefinisikan nama fungsi agar jejak stack dapat terbaca. Karena jika Anda memiliki kode seperti ini:

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

    Google Chrome akan mengingatkan ... kls.Hello ( ...tetapi sebagian besar peramban akan mengharapkan nama fungsi tepat setelah kata kunci functiondan akan memperlakukannya sebagai fungsi anonim. Chrome yang bahkan tidak dapat menggunakan Klassnama jika Anda tidak memberikan nama klske fungsi.

    Dan omong-omong, Anda dapat beralih ke fungsi printStackTrace opsi {guess: true}tapi saya tidak menemukan perbaikan nyata dengan melakukan itu.

  3. Tidak semua browser memberi Anda informasi yang sama. Yaitu, parameter, kolom kode, dll.


Nama Fungsi Penelepon

Ngomong-ngomong, jika Anda hanya ingin nama fungsi pemanggil (di sebagian besar browser, tetapi tidak di IE) Anda dapat menggunakan:

arguments.callee.caller.name

Tetapi perhatikan bahwa nama ini akan menjadi nama setelah functionkata kunci. Saya tidak menemukan cara (bahkan di Google Chrome) untuk mendapatkan lebih dari itu tanpa mendapatkan kode seluruh fungsi.


Kode Fungsi Penelepon

Dan meringkas sisa jawaban terbaik (oleh Pablo Cabrera, nourdine, dan Greg Hewgill). Satu-satunya cross-browser dan hal yang benar-benar aman yang dapat Anda gunakan adalah:

arguments.callee.caller.toString();

Yang akan menampilkan kode fungsi pemanggil. Sayangnya, itu tidak cukup bagi saya, dan itulah sebabnya saya memberi Anda tips untuk StackTrace dan Nama fungsi penelepon (meskipun mereka bukan cross-browser).

Mariano Desanze
sumber
1
mungkin Anda harus menambahkan jawabanFunction.caller per @ Greg
Zach Lysobey
Function.callertidak akan bekerja dalam mode ketat, namun.
Rickard Elimää
54

Saya tahu Anda menyebutkan "dalam Javascript", tetapi jika tujuannya adalah debugging, saya pikir lebih mudah untuk hanya menggunakan alat pengembang browser Anda. Ini adalah tampilannya di Chrome: Letakkan masukkan deskripsi gambar di sini saja debugger tempat Anda ingin menyelidiki tumpukan.

Phil
sumber
3
Ini adalah pertanyaan lama ... tapi ini jelas cara modern paling valid untuk melakukan ini hari ini.
markstewie
53

Untuk rekap (dan membuatnya lebih jelas) ...

kode ini:

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

setara dengan ini:

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

Jelas bit pertama lebih portabel, karena Anda dapat mengubah nama fungsi, katakan dari "Halo" menjadi "Ciao", dan semuanya masih berfungsi.

Dalam yang terakhir, jika Anda memutuskan untuk refactor nama fungsi yang dipanggil (Halo), Anda harus mengubah semua kemunculannya :(

nourdine
sumber
7
arguments.callee.caller selalu null di Chrome 25.0.1364.5 dev
Kokizzu
53

Anda bisa mendapatkan stacktrace lengkap:

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

Sampai penelepon null.

Catatan: ini menyebabkan loop tak terbatas pada fungsi rekursif.

ale5000
sumber
2
Maaf atas jawaban yang terlambat tetapi saya belum melihat komentar Anda sebelumnya; hanya untuk kasus rekursi tidak berfungsi, dalam kasus lain itu harus bekerja.
ale5000
45

Saya biasanya menggunakan (new Error()).stackChrome. Yang menyenangkan adalah bahwa ini juga memberi Anda nomor baris tempat pemanggil memanggil fungsi. The downside adalah bahwa ia membatasi panjang tumpukan hingga 10, itulah sebabnya saya datang ke halaman ini di tempat pertama.

(Saya menggunakan ini untuk mengumpulkan callstacks di konstruktor tingkat rendah selama eksekusi, untuk melihat dan men-debug nanti, jadi menetapkan breakpoint tidak digunakan karena akan dipukul ribuan kali)

mulai sekarang
sumber
Bisakah Anda menambahkan sedikit deskripsi tentang penjelasan yang Anda berikan?
abarisone
6
Ini adalah satu-satunya hal yang saya bisa mulai bekerja ketika 'use strict';ada di tempat. Memberi saya info yang saya butuhkan - terima kasih!
Jeremy Harris
4
Mengenai batas panjang tumpukan ... Anda dapat mengubahnya dengan "Error.stackTraceLimit = Infinity".
Tom
(Kesalahan baru ("StackLog")). stack.split ("\ n") membuatnya lebih baik untuk dibaca.
Teoman shipahi
36

Jika Anda tidak akan menjalankannya di IE <11 maka console.trace () akan sesuai.

function main() {
    Hello();
}

function Hello() {
    console.trace()
}

main()
// Hello @ VM261:9
// main @ VM261:4
permen karet
sumber
Bekerja! Harus ditambahkan lebih banyak suara
Krunal Panchal
22

Anda dapat menggunakan Function.Caller untuk mendapatkan fungsi panggilan. Metode lama menggunakan argument.caller dianggap usang.

Kode berikut menggambarkan penggunaannya:

function Hello() { return Hello.caller;}

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

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

Catatan tentang argument.caller usang: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller

Sadarilah Function.caller adalah non-standar: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller

Greg
sumber
1
Ini jawaban yang tepat hari ini. Anda tidak dapat melakukan hal-hal arguments.caller.callee lagi. Seandainya kita bisa memindahkan ini ke atas karena semua hal lainnya sudah usang sekarang.
coblr
4
Sepertinya ini tidak mungkin dalam mode ketat? Cannot access caller property of a strict mode function
Zach Lysobey
Function.caller tidak bekerja untuk saya dalam mode ketat juga. Juga, menurut MDN , function.caller adalah non-standar dan tidak boleh digunakan dalam produksi. Mungkin bisa digunakan untuk debugging.
jkdev
Saya tidak punya masalah dengan non-standar jika bekerja di Node, tetapi tidak diperbolehkan dalam mode ketat (saya diuji pada node 6.10). Hal yang sama berlaku untuk 'argumen'. Saya mendapat pesan kesalahan: '' 'penelepon' dan 'argumen' adalah properti fungsi terbatas dan tidak dapat diakses dalam konteks ini. "
Tom
21

Saya akan melakukan ini:

function Hello() {
  console.trace();
}
anorganik
sumber
Ini bekerja dengan baik! harus dengan diterima sebagai jawaban yang benar, karena cara-cara lain sudah tua \ tidak berfungsi lagi
Yuval Pruss
19
function Hello() {
    alert(Hello.caller);
}
Shadow2531
sumber
1
Dan hanya untuk nama fungsi gunakan Hello.caller.name
vanval
sama denganarguments.callee.caller.toString()
user2720864
Ini harus menjadi jawaban yang benar, setidaknya untuk 2016
Daniel
Ini bukan pada jalur standar, tetapi akan bekerja pada ECMAScript 5.
Obinna Nwakwue
1
@Aniel: tidak, seharusnya tidak. Lihat developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Dan Dascalescu
18

Ini lebih aman untuk digunakan *arguments.callee.callerkarena arguments.callersudah usang ...

Pablo Cabrera
sumber
36
arguments.calleejuga ditinggalkan dalam ES5, dan dihapus dalam mode ketat.
nyuszika7h
2
Apakah ada alternatif? Sunting: arguments.calleeadalah solusi buruk untuk masalah yang kini telah diselesaikan dengan lebih baik developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Matthew
16

Sepertinya ini adalah pertanyaan yang cukup terselesaikan tetapi saya baru-baru ini menemukan bahwa callee tidak diperbolehkan dalam 'mode ketat' jadi untuk penggunaan saya sendiri, saya menulis sebuah kelas yang akan mendapatkan jalur dari tempat ia dipanggil. Ini bagian dari lib pembantu kecil dan jika Anda ingin menggunakan kode standalone, ganti offset yang digunakan untuk mengembalikan jejak tumpukan pemanggil (gunakan 1 bukan 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
sumber
Tidak berfungsi untuk saya dengan function a(){ function b(){ function c(){ return ScriptPath(); } return c(); } return b(); } a()di konsol (belum mencoba dalam file), tetapi tampaknya memiliki ide yang masuk akal. Bagaimanapun harus ditingkatkan untuk visibilitas.
ninjagecko
Idenya bagus. Saya parsing berbeda tetapi dalam aplikasi nw.js, ini benar-benar satu-satunya ide yang memberikan apa yang saya cari.
Andrew Grothe
Berikan contoh cara memanggil fungsi ini.
pd_au
11

Cukup konsol catat tumpukan kesalahan Anda. Anda kemudian bisa tahu bagaimana Anda dipanggil

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

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

sello()

Prasanna
sumber
10

Dalam mode ES6 dan Strict, gunakan yang berikut untuk mendapatkan fungsi Caller

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

Harap dicatat bahwa, baris di atas akan mengeluarkan pengecualian, jika tidak ada penelepon atau tidak ada tumpukan sebelumnya. Gunakan yang sesuai.

Vanaga
sumber
Untuk mendapatkan callee (nama fungsi saat ini), gunakan: console.log((new Error()).stack.split("\n")[1].trim().split(" ")[1])
VanagaS
10

Pembaruan 2018

callerdilarang dalam mode ketat . Berikut adalah alternatif menggunakan Errortumpukan (non-standar) .

Fungsi berikut tampaknya melakukan pekerjaan di Firefox 52 dan Chrome 61-71 meskipun implementasinya membuat banyak asumsi tentang format logging dari dua browser dan harus digunakan dengan hati-hati, mengingat itu melemparkan pengecualian dan mungkin menjalankan dua regex pertandingan sebelum dilakukan.

'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
sumber
4
Itu luar biasa, dan juga mengerikan.
Ian
Saya mendapat "foo dipanggil dengan: hai di sana", tetapi foo tidak dipanggil dengan "hai di sana", log dipanggil dengan "hai di sana"
AndrewR
Benar, ada "pengubah salah tempat" dalam tata bahasa pesan kesalahan. Itu berarti mengatakan "log dipanggil dari fungsi f, ia ingin pesan X dicetak" tetapi dengan cara sesingkat mungkin.
Rovanion
7

Saya ingin menambahkan biola saya di sini untuk ini:

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

Saya menguji ini adalah chrome, safari dan IE (10 dan 8). Bekerja dengan baik. Hanya ada 1 fungsi yang penting, jadi jika Anda takut dengan biola besar, baca di bawah ini.

Catatan: Ada cukup banyak "boilerplate" saya sendiri dalam biola ini. Anda dapat menghapus semua itu dan menggunakan split jika Anda mau. Ini hanya seperangkat fungsi yang sangat aman yang saya andalkan.

Ada juga templat "JSFiddle" di sana yang saya gunakan untuk banyak biola untuk sekadar bermain biola cepat.

Bladnman
sumber
Saya ingin tahu apakah Anda dapat menambahkan "pembantu" sebagai ekstensi untuk prototipe dalam beberapa kasus, misalnya:String.prototype.trim = trim;
autis
6

Jika Anda hanya ingin nama fungsinya dan bukan kodenya, dan menginginkan solusi independen-peramban, gunakan yang berikut ini:

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

Perhatikan bahwa hal di atas akan mengembalikan kesalahan jika tidak ada fungsi pemanggil karena tidak ada elemen [1] dalam array. Untuk menyiasatinya, gunakan di bawah ini:

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
sumber
1
Ini telah ditinggalkan selama bertahun-tahun .
Dan Dascalescu
5

Hanya ingin membiarkan Anda tahu bahwa pada PhoneGap / Android yang namedoesnt tampaknya akan bekerja. Tetapi arguments.callee.caller.toString()akan melakukan trik.

Pablo Armentano
sumber
4

Di sini, semuanya kecuali functionnamedilucuti caller.toString(), dengan 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
sumber
ini masih mengembalikan seluruh deklarasi metode
Maslow
4

di sini adalah fungsi untuk mendapatkan stacktrace penuh :

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

sumber
3

jawaban heystewart dan jawaban JiarongWu keduanya menyebutkan bahwa Errorobjek memiliki akses ke stack.

Ini sebuah contoh:

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

Browser yang berbeda menunjukkan tumpukan dalam format string yang berbeda:

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)

Sebagian besar browser akan mengatur stack var stack = (new Error()).stack . Di Internet Explorer tumpukan akan tidak ditentukan - Anda harus melempar pengecualian nyata untuk mengambil tumpukan.

Kesimpulan: Ini mungkin untuk menentukan "utama" adalah penelepon untuk "Hello" menggunakan stackdalam Errorobjek. Bahkan itu akan bekerja dalam kasus di mana callee/ callerpendekatannya tidak berfungsi. Ini juga akan menunjukkan konteks kepada Anda, yaitu file sumber dan nomor baris. Namun diperlukan upaya untuk membuat solusi lintas platform.

Stephen Quan
sumber
2

Catatan Anda tidak dapat menggunakan Function.caller di Node.js, gunakan paket pemanggil-id sebagai gantinya. Sebagai contoh:

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
sumber
1

Coba kode berikut:

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

Bekerja untuk saya di Firefox-21 dan Chromium-25.

Diego Augusto Molina
sumber
Coba ini untuk fungsi rekursif.
daniel1426
arguments.calleetelah ditinggalkan selama bertahun-tahun .
Dan Dascalescu
1

Cara lain untuk mengatasi masalah ini adalah dengan hanya memberikan nama fungsi panggilan sebagai parameter.

Sebagai contoh:

function reformatString(string, callerName) {

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

    return string;
}

Sekarang, Anda bisa memanggil fungsi seperti ini:

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

    reformatString(myString, function.name);
}

Contoh saya menggunakan cek kode nama fungsi, tetapi Anda dapat dengan mudah menggunakan pernyataan switch atau logika lain untuk melakukan apa yang Anda inginkan di sana.

GrayedFox
sumber
Saya percaya ini juga memecahkan masalah kompatibilitas lintas browser, sebagian besar. Tapi tolong uji ini sebelum menganggapnya benar! ( Mulai berkeringat )
GrayedFox
1

Sejauh yang saya tahu, kami memiliki 2 cara untuk ini dari sumber yang diberikan seperti ini-

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

Pikirkan jawaban Anda :).

Abrar Jahin
sumber
Ini telah ditinggalkan selama bertahun-tahun , dan Function.caller tidak berfungsi dalam mode ketat.
Dan Dascalescu
1

Mengapa semua solusi di atas terlihat seperti ilmu roket. Sementara itu, seharusnya tidak lebih rumit dari cuplikan ini. Semua kredit untuk orang ini

Bagaimana Anda mengetahui fungsi pemanggil dalam 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)]
Anonim
sumber
3
Inilah yang saya dapatkan dengan menggunakan ini: TypeError: properti 'pemanggil', 'callee', dan 'argumen' mungkin tidak dapat diakses pada fungsi mode ketat atau objek argumen untuk panggilan ke mereka. Adakah ide cara mengerjakan ini dalam mode ketat?
hard_working_ant
1

Saya mencoba menjawab pertanyaan dan hadiah saat ini dengan pertanyaan ini.

Karunia itu mengharuskan pemanggil diperoleh dalam mode ketat , dan satu-satunya cara saya bisa melihat ini dilakukan adalah dengan merujuk ke fungsi yang dinyatakan di luar mode ketat.

Sebagai contoh, berikut ini adalah non-standar tetapi telah diuji dengan versi sebelumnya (29/03/2016) dan saat ini (1 Agustus 2018) Chrome, Edge dan 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();

autis
sumber
Retasan bagus, tetapi tidak akan bekerja untuk modul ES5, yang seluruhnya dalam mode ketat .
Dan Dascalescu
0

Jika Anda benar-benar membutuhkan fungsionalitas untuk beberapa alasan dan ingin itu kompatibel lintas-browser dan tidak khawatir untuk hal-hal yang ketat dan maju kompatibel kemudian berikan referensi ini:

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
sumber
0

Saya pikir potongan kode berikut mungkin bermanfaat:

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

Jalankan kode:

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

Log terlihat seperti ini:

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
sumber