function main()
{
Hello();
}
function Hello()
{
// How do you find out the caller function is 'main'?
}
Apakah ada cara untuk mengetahui tumpukan panggilan?
function main()
{
Hello();
}
function Hello()
{
// How do you find out the caller function is 'main'?
}
Apakah ada cara untuk mengetahui tumpukan panggilan?
Jawaban:
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());
}
arguments.callee.caller.name
akan mendapatkan nama fungsi.
'use strict';
mungkin membantu.
arguments
BISA 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.
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:
Sangat lambat untuk mendapatkan jejak tumpukan jadi berhati-hatilah (baca ini lebih lanjut).
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 function
dan akan memperlakukannya sebagai fungsi anonim. Chrome yang bahkan tidak dapat menggunakan Klass
nama jika Anda tidak memberikan nama kls
ke fungsi.
Dan omong-omong, Anda dapat beralih ke fungsi printStackTrace opsi {guess: true}
tapi saya tidak menemukan perbaikan nyata dengan melakukan itu.
Tidak semua browser memberi Anda informasi yang sama. Yaitu, parameter, kolom kode, dll.
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 function
kata kunci. Saya tidak menemukan cara (bahkan di Google Chrome) untuk mendapatkan lebih dari itu tanpa mendapatkan kode seluruh fungsi.
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).
Function.caller
tidak akan bekerja dalam mode ketat, namun.
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 saja debugger tempat Anda ingin menyelidiki tumpukan.
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 :(
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.
Saya biasanya menggunakan (new Error()).stack
Chrome. 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)
'use strict';
ada di tempat. Memberi saya info yang saya butuhkan - terima kasih!
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
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
Cannot access caller property of a strict mode function
Saya akan melakukan ini:
function Hello() {
console.trace();
}
function Hello() {
alert(Hello.caller);
}
arguments.callee.caller.toString()
Ini lebih aman untuk digunakan *arguments.callee.caller
karena arguments.caller
sudah usang ...
arguments.callee
juga ditinggalkan dalam ES5, dan dihapus dalam mode ketat.
arguments.callee
adalah solusi buruk untuk masalah yang kini telah diselesaikan dengan lebih baik developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
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('.');
};
}
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.
Coba akses ini:
arguments.callee.caller.name
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()
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.
console.log((new Error()).stack.split("\n")[1].trim().split(" ")[1])
caller
dilarang dalam mode ketat . Berikut adalah alternatif menggunakan Error
tumpukan (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();
}());
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.
String.prototype.trim = trim;
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]);
Hanya ingin membiarkan Anda tahu bahwa pada PhoneGap / Android yang name
doesnt tampaknya akan bekerja. Tetapi arguments.callee.caller.toString()
akan melakukan trik.
Di sini, semuanya kecuali functionname
dilucuti 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>
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;
}
jawaban heystewart dan jawaban JiarongWu keduanya menyebutkan bahwa Error
objek 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 stack
dalam Error
objek. Bahkan itu akan bekerja dalam kasus di mana callee
/ caller
pendekatannya tidak berfungsi. Ini juga akan menunjukkan konteks kepada Anda, yaitu file sumber dan nomor baris. Namun diperlukan upaya untuk membuat solusi lintas platform.
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
}
*/
}
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.
arguments.callee
telah ditinggalkan selama bertahun-tahun .
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.
Sejauh yang saya tahu, kami memiliki 2 cara untuk ini dari sumber yang diberikan seperti ini-
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;
}
}
Pikirkan jawaban Anda :).
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)]
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();
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
}
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