JavaScript에서 호출자 함수를 어떻게 찾습니까?
function main()
{
Hello();
}
function Hello()
{
// How do you find out the caller function is 'main'?
}
호출 스택을 찾는 방법이 있습니까?
function Hello()
{
alert("caller is " + Hello.caller);
}
이 기능은 다음 에서 비표준 입니다 Function.caller
.
비표준
이 기능은 비표준이며 표준 트랙에 없습니다. 웹에 접하는 프로덕션 사이트에서는 사용하지 마십시오. 모든 사용자에게 작동하지 않습니다. 구현간에 큰 비 호환성이있을 수 있으며 향후 동작이 변경 될 수 있습니다.
다음은 더 이상 최신 Javascript에서 지원되지 않는 2008의 이전 답변입니다.
function Hello()
{
alert("caller is " + arguments.callee.caller.toString());
}
StackTrace
브라우저 별 코드를 사용하여 전체 스택 추적을 찾을 수 있습니다. 좋은 것은 누군가 이미 그것을 만들었다는 것입니다 . 다음은 GitHub 의 프로젝트 코드입니다 .
그러나 모든 뉴스가 좋은 것은 아닙니다.
정말 (읽기 스택 추적이 너무 조심해야 얻을 둔화되고 이 이상).
스택 추적을 읽을 수 있도록 함수 이름을 정의해야합니다. 다음과 같은 코드가있는 경우 :
var Klass = function kls() { this.Hello = function() { alert(printStackTrace().join('\n\n')); }; } new Klass().Hello();
Google 크롬은 경고를 표시
... kls.Hello ( ...
하지만 대부분의 브라우저는 키워드 바로 뒤에 함수 이름을 예상하고function
이를 익명 함수로 처리합니다. 함수에Klass
이름kls
을 지정하지 않으면 Chrome조차도 이름 을 사용할 수 없습니다 .{guess: true}
그건 그렇고, printStackTrace 함수에 옵션을 전달할 수는 있지만 그렇게함으로써 실질적인 개선을 찾지 못했습니다.모든 브라우저가 동일한 정보를 제공하는 것은 아닙니다. 즉, 매개 변수, 코드 열 등입니다.
호출자 함수 이름
그건 그렇고, (대부분의 브라우저에서 IE가 아닌) 호출자 함수의 이름 만 원한다면 다음을 사용할 수 있습니다.
arguments.callee.caller.name
그러나이 이름은 function
키워드 다음의 이름이됩니다 . 전체 기능의 코드를 얻지 않고는 (Google 크롬에서도) 그 이상을 얻을 방법을 찾지 못했습니다.
발신자 기능 코드
나머지 베스트 답변을 요약합니다 (Pablo Cabrera, nourdine 및 Greg Hewgill 작성). 사용할 수있는 유일한 크로스 브라우저이자 정말 안전한 방법은 다음과 같습니다.
arguments.callee.caller.toString();
호출자 함수 의 코드 가 표시 됩니다. 슬프게도 이것만으로는 충분하지 않습니다. 이것이 바로 StackTrace와 호출자 함수 이름에 대한 팁을 제공하는 이유입니다 (브라우저 간은 아니지만).
요약하면 (그리고 더 명확하게) ...
이 코드 :
function Hello() {
alert("caller is " + arguments.callee.caller.toString());
}
다음과 같습니다.
function Hello() {
alert("caller is " + Hello.caller.toString());
}
함수의 이름을 "Hello"에서 "Ciao"로 바꾸어도 모든 것을 작동시킬 수 있기 때문에 첫 번째 비트는 더 이식성이 뛰어납니다.
후자의 경우 호출 된 함수의 이름 (Hello)을 리팩터링하기로 결정한 경우 모든 발생을 변경해야합니다.
전체 스택 추적을 얻을 수 있습니다.
arguments.callee.caller
arguments.callee.caller.caller
arguments.callee.caller.caller.caller
발신자가 null
.
참고 : 재귀 함수에서 무한 루프가 발생합니다.
"자바 스크립트에서"라고 언급 한 것을 알고 있지만 디버깅이 목적이라면 브라우저의 개발자 도구를 사용하는 것이 더 쉽다고 생각합니다. 이것이 Chrome에서 보이는 방식 입니다. 스택을 조사 할 디버거를 놓기 만하면됩니다.
저는 보통 (new Error()).stack
Chrome에서 사용 합니다. 좋은 점은 호출자가 함수를 호출 한 줄 번호도 제공한다는 것입니다. 단점은 스택의 길이를 10으로 제한한다는 것입니다. 이것이 제가 처음에이 페이지를 찾은 이유입니다.
(실행 중에 저수준 생성자에서 콜 스택을 수집하고 나중에보고 디버그하기 위해 이것을 사용하고 있으므로 중단 점을 설정하는 것은 수천 번에 해당하므로 쓸모가 없습니다)
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
function Hello() {
alert(Hello.caller);
}
그것은 사용하기 더 안전 *arguments.callee.caller
하기 때문에 arguments.caller
되어 사용되지 ...
이것은 꽤 해결 된 질문처럼 보이지만 최근에 피 호출자가 '엄격 모드'에서 허용되지 않는다는 것을 알게 되었으므로 내 자신의 용도로 호출되는 경로를 가져올 클래스를 작성했습니다. 작은 도우미 라이브러리 의 일부이며 코드를 독립 실행 형으로 사용하려면 호출자의 스택 추적을 반환하는 데 사용되는 오프셋을 변경합니다 (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 Hello() {
console.trace();
}
이것에 액세스하십시오 :
arguments.callee.caller.name
콘솔에서 오류 스택을 기록하십시오. 그런 다음 어떻게 전화를 받고 있는지 알 수 있습니다.
const hello = () => {
console.log(new Error('I was called').stack)
}
const sello = () => {
hello()
}
sello()
2018 업데이트
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 with:', ...messages);
} else {
console.log(fnName(logLines[2]), 'called with:', ...messages);
}
} else {
console.log(...messages);
}
}
function foo() {
log('hi', 'there');
}
(function main() {
foo();
}());
여기에 내 바이올린을 추가하고 싶었습니다.
http://jsfiddle.net/bladnman/EhUm3/
나는 이것이 크롬, 사파리 및 IE (10 및 8)임을 테스트했습니다. 잘 작동합니다. 중요한 기능은 하나뿐이므로 큰 바이올린에 겁이 나면 아래를 읽으십시오.
참고 :이 바이올린에는 내 자신의 "보일러 플레이트"가 상당히 많이 있습니다. 원하는 경우 모든 것을 제거하고 분할을 사용할 수 있습니다. 그것은 제가 의지하게 된 매우 안전한 "기능의 집합 일뿐입니다.
거기에 "JSFiddle"템플릿이 있는데,이 템플릿은 간단한 조작을 위해 많은 바이올린에 사용합니다.
코드가 아닌 함수 이름 만 원하고 브라우저 독립적 인 솔루션을 원하면 다음을 사용하십시오.
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>
function stacktrace() {
var f = stacktrace;
var stack = 'Stack trace:';
while (f) {
stack += '\n' + f.name;
f = f.caller;
}
return stack;
}
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에서 스택은 정의되지 않습니다. 스택을 검색하려면 실제 예외를 발생시켜야합니다.
결론 : 개체 stack
에서를 사용하여 "main"이 "Hello"에 대한 호출자임을 확인할 수 있습니다 Error
. 실제로 callee
/ caller
접근 방식이 작동하지 않는 경우에도 작동합니다. 또한 컨텍스트, 즉 소스 파일과 줄 번호를 보여줍니다. 그러나 솔루션을 교차 플랫폼으로 만들려면 노력이 필요합니다.
ES6 및 Strict 모드에서 다음을 사용하여 Caller 함수를 가져옵니다.
console.log((new Error()).stack.split("\n")[2].trim().split(" ")[1])
호출자가 없거나 이전 스택이없는 경우 위 줄에서 예외가 발생합니다. 그에 따라 사용하십시오.
다음 코드를 시도하십시오.
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에서 나를 위해 일했습니다.
이 문제를 해결하는 또 다른 방법은 호출하는 함수의 이름을 매개 변수로 전달하는 것입니다.
예를 들면 :
function reformatString(string, callerName) {
if (callerName === "uid") {
string = string.toUpperCase();
}
return string;
}
이제 다음과 같이 함수를 호출 할 수 있습니다.
function uid(){
var myString = "apples";
reformatString(myString, function.name);
}
내 예에서는 함수 이름의 하드 코딩 된 검사를 사용하지만 스위치 문이나 다른 논리를 사용하여 원하는 작업을 쉽게 수행 할 수 있습니다.
내가 아는 한, 우리는 이와 같은 주어진 소스에서 이것을위한 두 가지 방법이 있습니다.
-
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)]
나는이 질문에 대한 질문과 현재 현상금을 모두 해결하려고 노력하고 있습니다.
현상금은 호출자가 엄격 모드 에서 얻어 져야하며 , 이것이 수행되는 것을 볼 수있는 유일한 방법 은 엄격 모드 외부 에서 선언 된 함수를 참조하는 것입니다 .
예를 들어 다음은 비표준이지만 Chrome, Edge 및 Firefox의 이전 버전 (2016 년 3 월 29 일) 및 현재 버전 (2018 년 8 월 1 일)에서 테스트되었습니다.
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
이전 답변 중 어느 것도 내가 찾던 것과 같이 작동하지 않기 때문에 (문자열이나 호출 스택이 아닌 마지막 함수 호출자 만 가져옴) 나와 같은 사람들을 위해 여기에 솔루션을 게시하고 이것이 그들에게 효과가 있기를 바랍니다.
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();
참고 URL : https://stackoverflow.com/questions/280389/how-do-you-find-out-the-caller-function-in-javascript
'Development Tip' 카테고리의 다른 글
특정 버전의 루비 보석을 설치하는 방법은 무엇입니까? (0) | 2020.09.28 |
---|---|
C ++ 프로그래머가 'new'사용을 최소화해야하는 이유는 무엇입니까? (0) | 2020.09.28 |
onActivityResult가 Fragment에서 호출되지 않습니다. (0) | 2020.09.28 |
REST API / 웹 서비스 보안을위한 모범 사례 (0) | 2020.09.28 |
Bash 스크립트에서 인수를 반복하는 방법 (0) | 2020.09.28 |