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 년의 오래된 답변으로, 현대 Javascript에서 더 이상 지원되지 않습니다.
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();
Chrome은 경고 ... kls.Hello ( ...
하지만 대부분의 브라우저는 키워드 바로 다음에 함수 이름을 예상하고 function
이를 익명 함수로 취급합니다. 함수에 Klass
이름 kls
을 지정하지 않으면 Chrome조차도 이름 을 사용할 수 없습니다 .
{guess: true}
그건 그렇고, printStackTrace 함수에 옵션을 전달할 수는 있지만 그렇게해도 실제로 개선되지는 않았습니다.
모든 브라우저가 동일한 정보를 제공하는 것은 아닙니다. 즉, 매개 변수, 코드 열 등
그런데 호출자 함수의 이름 만 원한다면 (대부분의 브라우저에서 IE는 아님) 다음을 사용할 수 있습니다.
arguments.callee.caller.name
그러나이 이름은 function
키워드 다음에 나오는 이름입니다 . 전체 기능의 코드를 얻지 않고 그 이상을 얻을 수있는 방법은 없습니다 (Chrome에서도).
그리고 나머지 최고의 답변을 요약합니다 (Pablo Cabrera, nourdine 및 Greg Hewgill). 사용할 수있는 유일한 브라우저 간 안전한 브라우저는 다음과 같습니다.
arguments.callee.caller.toString();
호출자 함수 의 코드 가 표시 됩니다. 슬프게도, 그것은 충분하지 않기 때문에 StackTrace와 호출자 함수 이름에 대한 팁을 제공합니다 (크로스 브라우저는 아니지만).
Function.caller
그러나 엄격 모드에서는 작동하지 않습니다.
"자바 스크립트로"언급했지만, 목적이 디버깅이라면 브라우저의 개발자 도구를 사용하는 것이 더 쉽다고 생각합니다. Chrome에서 다음과 같이 표시됩니다. 스택을 조사 할 위치에 디버거를 놓습니다.
요약하자면 (더 명확하게) ...
이 코드 :
function Hello() {
alert("caller is " + arguments.callee.caller.toString());
}
이것과 같습니다 :
function Hello() {
alert("caller is " + Hello.caller.toString());
}
함수 이름을 "Hello"에서 "Ciao"로 변경하고 여전히 모든 작업을 수행 할 수 있기 때문에 첫 번째 비트는 더 이식성이 뛰어납니다.
후자의 경우 호출 된 함수 (Hello)의 이름을 리팩토링하기로 결정한 경우 모든 발생을 변경해야합니다. (
나는 보통 (new Error()).stack
Chrome에서 사용 합니다. 좋은 점은 호출자가 함수를 호출 한 행 번호를 제공한다는 것입니다. 단점은 스택 길이를 10으로 제한한다는 것입니다. 그래서 처음 에이 페이지에 왔습니다.
(저는 실행 중에 하위 수준 생성자에서 콜 스택을 수집하고 나중에보고 디버그하기 위해 이것을 사용하고 있으므로 중단 점을 설정하는 것은 수천 번에 도달하기 때문에 사용되지 않습니다)
'use strict';
자리에 있을 때 일할 수있는 유일한 것 입니다. 필요한 정보를 알려주십시오. 감사합니다!
IE <11에서 실행하지 않으면 console.trace () 가 적합합니다.
function main() {
Hello();
}
function Hello() {
console.trace()
}
main()
// Hello @ VM261:9
// main @ VM261:4
Function.Caller를 사용하여 호출 기능을 얻을 수 있습니다. argument.caller를 사용하는 이전 방법은 사용되지 않는 것으로 간주됩니다.
다음 코드는 그 사용법을 보여줍니다.
function Hello() { return Hello.caller;}
Hello2 = function NamedFunc() { return NamedFunc.caller; };
function main()
{
Hello(); //both return main()
Hello2();
}
더 이상 사용되지 않는 argument.caller에 대한 참고 사항 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller
Function.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() {
console.trace();
}
function Hello() {
alert(Hello.caller);
}
arguments.callee.caller.toString()
그것은 사용하기 더 안전 *arguments.callee.caller
하기 때문에 arguments.caller
되어 사용되지 ...
arguments.callee
ES5에서는 더 이상 사용되지 않으며 엄격 모드에서는 제거됩니다.
arguments.callee
더 잘 해결 한 문제에 대한 나쁜 해결책이었습니다.
이것은 상당히 해결 된 질문처럼 보이지만 최근에 수신자가 '엄격 모드'에서 허용되지 않는다는 것을 알았 으므로 내 용도로 호출 된 경로를 얻을 수있는 클래스를 작성했습니다. 작은 도우미 라이브러리 의 일부이며 코드 독립 실행 형을 사용하려면 호출자의 스택 추적을 반환하는 데 사용되는 오프셋을 변경하십시오 (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()
콘솔에서 (파일에 시도하지 않은), 그러나 합리적인 생각을 갖고있는 것 같아요. 어쨌든 가시성을 위해 upvoted해야합니다.
caller
엄격 모드에서는 금지되어 있습니다 . 다음은 (비표준) Error
스택을 사용하는 대안 입니다.
다음 함수는 Firefox 52 및 Chrome 61-71에서 작동하는 것처럼 보이지만 구현시 두 브라우저의 로깅 형식에 대해 많은 가정이 이루어지며 예외가 발생하고 두 개의 정규 표현식을 실행할 수 있으므로주의해서 사용해야합니다 완료하기 전에 일치합니다.
'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();
}());
여기에 바이올린을 추가하고 싶었습니다.
http://jsfiddle.net/bladnman/EhUm3/
크롬, 사파리 및 IE (10 및 8)입니다. 잘 작동합니다. 중요한 기능은 1 개뿐이므로 큰 바이올린이 두려운 경우 아래를 읽으십시오.
참고 :이 바이올린에는 상당히 많은 양의 "보일러 플레이트"가 있습니다. 원하는 경우 모든 것을 제거하고 split을 사용할 수 있습니다. 내가 사용하게 된 기능은 매우 안전합니다.
거기에는 "JSFiddle"템플릿도 있습니다. 많은 바이올린을 사용하여 간단하게 속일 수 있습니다.
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]);
그냥 당신이에 있음을 알려 할 폰갭 / 안드로이드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>
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
. Internet Explorer에서 스택은 정의되지 않습니다. 스택을 검색하려면 실제 예외를 처리해야합니다.
결론 : "main"이 객체 stack
에서 "Hello"를 호출 한 사람인지 확인할 수 있습니다 Error
. 실제로 callee
/ caller
접근 방식이 작동하지 않는 경우 작동합니다. 또한 문맥, 즉 소스 파일과 줄 번호를 보여줍니다. 그러나 솔루션을 교차 플랫폼으로 만들려면 노력이 필요합니다.
Node.js에서는 Function.caller 를 사용할 수 없으며 대신 caller-id 패키지를 사용하십시오. 예를 들면 다음과 같습니다.
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;
}
Firefox-21 및 Chromium-25에서 나를 위해 일했습니다.
arguments.callee
된 여러 해 동안 사용되지 않습니다 .
이 문제를 해결하는 또 다른 방법은 단순히 호출 함수의 이름을 매개 변수로 전달하는 것입니다.
예를 들면 다음과 같습니다.
function reformatString(string, callerName) {
if (callerName === "uid") {
string = string.toUpperCase();
}
return string;
}
이제 다음과 같이 함수를 호출 할 수 있습니다.
function uid(){
var myString = "apples";
reformatString(myString, function.name);
}
필자의 예제는 함수 이름에 대한 하드 코딩 된 검사를 사용하지만 switch 문이나 다른 논리를 사용하여 원하는 것을 쉽게 수행 할 수 있습니다.
내가 아는 한, 우리는 이것과 같은 주어진 출처에서 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;
}
}
당신의 대답이 있다고 생각하십시오 :).
위의 모든 솔루션이 로켓 과학처럼 보이는 이유 한편,이 스 니펫보다 더 복잡하지 않아야합니다. 이 사람에 대한 모든 크레딧
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)]
이 질문으로 질문과 현재 현상금을 모두 해결하려고합니다.
현상금은 발신자를 엄격 모드 로 가져와야하며이를 볼 수있는 유일한 방법은 외부에서 선언 된 함수를 참조하는 것입니다 은 엄격 모드 에서 .
예를 들어, 다음은 비표준이지만 다음 버전 (2016 년 3 월 29 일) 및 현재 버전 (2018 년 8 월 1 일)의 Chrome, Edge 및 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();
어떤 이유로 든 기능이 정말로 필요하고 브라우저 간 호환이 가능하고 엄격한 것들에 대해 걱정하지 않고 앞으로 호환되도록하려면 다음 참조를 전달하십시오.
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