JavaScript에서 호출자 함수를 어떻게 찾습니까?


865
function main()
{
   Hello();
}

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

통화 스택을 찾는 방법이 있습니까?


63
이것이 디버깅에 도움이되기를 바랍니다. 발신자를 기반으로하는 다양한 행동은 나쁜 생각입니다.
OJ.

언제 디버깅에 유용합니까?
Anderson Green

33
@AndersonGreen 예를 들어 기본 템플릿 렌더링 메소드가 있고 두 번 호출되는 것을 볼 때. 1000 개의 LoC를 통해 빗나가거나 디버거를 사용하는 데 어려움을 겪지 않고 당시의 스택이 무엇인지 알 수 있습니다.
tkone

28
스택 추적을 보려면 chrome에 console.trace ()를 사용하십시오. 하지만 다른 사람에 대해 알고하지 않습니다
lukas.pukenis

5
왜 이것이 나쁜 생각입니까?
Jacob Schneider

답변:


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

이 기능은 다음 에서 비표준 입니다 Function.caller.

비표준
이 기능은 비표준이며 표준 트랙이 아닙니다. 웹이있는 프로덕션 사이트에서는 사용하지 마십시오. 모든 사용자에게 적용되는 것은 아닙니다. 구현 간에는 큰 비 호환성이있을 수 있으며 향후 동작이 변경 될 수 있습니다.


다음은 2008 년의 오래된 답변으로, 현대 Javascript에서 더 이상 지원되지 않습니다.

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

254
arguments.callee.caller.name함수의 이름을 얻습니다.
로켓 Hazmat

137
" 'caller', 'callee'및 'arguments'속성은 엄격 모드 함수 또는 호출에 대한 인수 객체에서 액세스 할 수 없습니다."-ES5에서 더 이상 사용되지 않으며 엄격 모드에서 제거됩니다.
ThatGuy

12
엄격 모드를 사용하지 않는 경우에만 작동합니다. 따라서 제거하면 'use strict';도움이 될 수 있습니다.
pvorb

23
arguments엄격 모드의 함수 내에서 액세스 할 수 있습니다. function.arguments에서 온 것이 아닙니다. 또한 명명 된 인수가있는 경우 인수 [i] 형식은 함수 내에서 명명 된 버전의 변경 사항을 추적하지 않습니다.
rvr_jon

41
이 게시물은 2011 년에 게시 된 이후 더 이상 사용되지 않습니다. 기본 설정 방법은 이제 Function.caller입니다 (2015 년 기준).
Greg

152

스택 트레이스

브라우저 별 코드를 사용하여 전체 스택 추적을 찾을 수 있습니다. 좋은 점은 누군가 이미 만든 것입니다 . 다음은 GitHub프로젝트 코드입니다 .

그러나 모든 뉴스가 좋은 것은 아닙니다.

  1. 정말 (읽기 스택 추적이 너무 조심해야 얻을 둔화되고 이상).

  2. 스택 추적을 읽을 수 있도록 함수 이름을 정의해야합니다. 다음과 같은 코드가 있다면 :

    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 함수에 옵션을 전달할 수는 있지만 그렇게해도 실제로 개선되지는 않았습니다.

  3. 모든 브라우저가 동일한 정보를 제공하는 것은 아닙니다. 즉, 매개 변수, 코드 열 등


발신자 기능 이름

그런데 호출자 함수의 이름 만 원한다면 (대부분의 브라우저에서 IE는 아님) 다음을 사용할 수 있습니다.

arguments.callee.caller.name

그러나이 이름은 function키워드 다음에 나오는 이름입니다 . 전체 기능의 코드를 얻지 않고 그 이상을 얻을 수있는 방법은 없습니다 (Chrome에서도).


발신자 기능 코드

그리고 나머지 최고의 답변을 요약합니다 (Pablo Cabrera, nourdine 및 Greg Hewgill). 사용할 수있는 유일한 브라우저 간 안전한 브라우저는 다음과 같습니다.

arguments.callee.caller.toString();

호출자 함수 의 코드 가 표시 됩니다. 슬프게도, 그것은 충분하지 않기 때문에 StackTrace와 호출자 함수 이름에 대한 팁을 제공합니다 (크로스 브라우저는 아니지만).


1
아마 당신은 Function.caller
@Greg

Function.caller그러나 엄격 모드에서는 작동하지 않습니다.
Rickard Elimää

54

"자바 스크립트로"언급했지만, 목적이 디버깅이라면 브라우저의 개발자 도구를 사용하는 것이 더 쉽다고 생각합니다. Chrome에서 다음과 여기에 이미지 설명을 입력하십시오 같이 표시됩니다. 스택을 조사 할 위치에 디버거를 놓습니다.


3
이것은 오래된 질문입니다 ...하지만 이것은 오늘날 이것을하는 가장 현대적인 가장 유효한 방법입니다.
markstewie

53

요약하자면 (더 명확하게) ...

이 코드 :

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

이것과 같습니다 :

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

함수 이름을 "Hello"에서 "Ciao"로 변경하고 여전히 모든 작업을 수행 할 수 있기 때문에 첫 번째 비트는 더 이식성이 뛰어납니다.

후자의 경우 호출 된 함수 (Hello)의 이름을 리팩토링하기로 결정한 경우 모든 발생을 변경해야합니다. (


7
Chrome에서 arguments.callee.caller는 항상 null입니다. 25.0.1364.5 dev
Kokizzu

53

전체 스택 추적을 얻을 수 있습니다.

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

호출자가 될 때까지 null.

참고 : 재귀 함수에 무한 루프가 발생합니다.


2
답장을 늦게 미안하지만 이전에 귀하의 의견을 보지 못했습니다. 재귀 경우에만 작동하지 않으며 다른 경우에는 작동합니다.
ale5000

45

나는 보통 (new Error()).stackChrome에서 사용 합니다. 좋은 점은 호출자가 함수를 호출 한 행 번호를 제공한다는 것입니다. 단점은 스택 길이를 10으로 제한한다는 것입니다. 그래서 처음 에이 페이지에 왔습니다.

(저는 실행 중에 하위 수준 생성자에서 콜 스택을 수집하고 나중에보고 디버그하기 위해 이것을 사용하고 있으므로 중단 점을 설정하는 것은 수천 번에 도달하기 때문에 사용되지 않습니다)


제공 한 설명에 대해 조금 더 설명해 주시겠습니까?
abarisone

6
이것이 내가 'use strict';자리에 있을 때 일할 수있는 유일한 것 입니다. 필요한 정보를 알려주십시오. 감사합니다!
제레미 해리스

4
스택 길이 제한에 대해서는 "Error.stackTraceLimit = Infinity"를 사용하여 변경할 수 있습니다.
Tom

(new Error ( "StackLog")). stack.split ( "\ n") 더보기 좋게 만듭니다.
Teoman shipahi

36

IE <11에서 실행하지 않으면 console.trace () 가 적합합니다.

function main() {
    Hello();
}

function Hello() {
    console.trace()
}

main()
// Hello @ VM261:9
// main @ VM261:4

작동합니다! 더 많은 투표를해야합니다
Krunal Panchal

22

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


1
요즘 정답입니다. 더 이상 arguments.caller.callee 작업을 수행 할 수 없습니다. 다른 모든 것들이 이제 구식이기 때문에 이것을 맨 위로 가져갈 수 있기를 바랍니다.
coblr

4
엄격 모드에서는 불가능한 것 같습니다? Cannot access caller property of a strict mode function
Zach Lysobey

엄격한 모드에서도 Function.caller가 작동하지 않았습니다. 또한 MDN에 따르면 function.caller는 비표준이므로 프로덕션 환경에서 사용해서는 안됩니다. 그래도 디버깅에는 효과가있을 수 있습니다.
jkdev

노드에서 작동하면 비표준에 문제가 없지만 엄격 모드에서는 허용되지 않습니다 (노드 6.10에서 테스트). '인수'에도 동일하게 적용됩니다. '' '호출자'및 '인수'는 제한된 기능 속성
Tom

21

나는 이것을 할 것이다 :

function Hello() {
  console.trace();
}

이것은 잘 작동합니다! 다른 방법은 더 이상 작동하지 않기 때문에 정답으로 받아 들여 져야합니다
Yuval Pruss



16

이것은 상당히 해결 된 질문처럼 보이지만 최근에 수신자가 '엄격 모드'에서 허용되지 않는다는 것을 알았 으므로 내 용도로 호출 된 경로를 얻을 수있는 클래스를 작성했습니다. 작은 도우미 라이브러리일부이며 코드 독립 실행 형을 사용하려면 호출자의 스택 추적을 반환하는 데 사용되는 오프셋을 변경하십시오 (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해야합니다.
ninjagecko

아이디어는 훌륭합니다. 나는 다르게 파싱하고 있지만 nw.js 앱에서는 이것이 내가 찾고있는 것을주는 유일한 아이디어입니다.
Andrew Grothe 2016 년

이 함수를 호출하는 방법의 예를 제공하십시오.
pd_au 2016 년


11

오류 스택을 콘솔 로그하십시오. 그러면 어떻게 부름을 받고 있는지 알 수 있습니다

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

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

sello()


10

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


4
그것은 믿기 어려우며 끔찍합니다.
Ian

"foo there with : hi there"가 있지만 foo 는 "hi there"로 호출되지 않았습니다. 로그 는 "hi there"로 호출되었습니다.
AndrewR

오른쪽, 오류 메시지의 문법에 "잘못 배치 된 수정 자"가있었습니다. "로그가 함수 f에서 호출되었고, X 메시지가 인쇄되기를 원했습니다."
Rovanion

9

ES6 및 Strict 모드에서 다음을 사용하여 발신자 기능을 얻습니다.

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

호출자가 없거나 이전 스택이 없으면 위의 행에서 예외가 발생합니다. 그에 따라 사용하십시오.


수신자 (현재 기능 이름)를 얻으려면 다음을 사용하십시오. console.log((new Error()).stack.split("\n")[1].trim().split(" ")[1])
VanagaS

7

여기에 바이올린을 추가하고 싶었습니다.

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

크롬, 사파리 및 IE (10 및 8)입니다. 잘 작동합니다. 중요한 기능은 1 개뿐이므로 큰 바이올린이 두려운 경우 아래를 읽으십시오.

참고 :이 바이올린에는 상당히 많은 양의 "보일러 플레이트"가 있습니다. 원하는 경우 모든 것을 제거하고 split을 사용할 수 있습니다. 내가 사용하게 된 기능은 매우 안전합니다.

거기에는 "JSFiddle"템플릿도 있습니다. 많은 바이올린을 사용하여 간단하게 속일 수 있습니다.


어떤 경우에는 "헬퍼"를 프로토 타입의 확장으로 추가 할 수 있는지 궁금합니다.String.prototype.trim = trim;
자폐증

6

코드가 아닌 함수 이름 만 원하고 브라우저 독립적 인 솔루션을 원하면 다음을 사용하십시오.

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


5

그냥 당신이에 있음을 알려 할 폰갭 / 안드로이드name 나던 작동하는 것 같다. 그러나 arguments.callee.caller.toString()트릭을 할 것입니다.


4

여기서 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>

이것은 여전히 ​​전체 메소드 선언을 반환합니다
Maslow

4

다음은 전체 스택 추적얻는 함수입니다 .

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

3

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접근 방식이 작동하지 않는 경우 작동합니다. 또한 문맥, 즉 소스 파일과 줄 번호를 보여줍니다. 그러나 솔루션을 교차 플랫폼으로 만들려면 노력이 필요합니다.


2

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
    }
    */
}

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에서 나를 위해 일했습니다.


재귀 함수에 이것을 시도하십시오.
daniel1426


1

이 문제를 해결하는 또 다른 방법은 단순히 호출 함수의 이름을 매개 변수로 전달하는 것입니다.

예를 들면 다음과 같습니다.

function reformatString(string, callerName) {

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

    return string;
}

이제 다음과 같이 함수를 호출 할 수 있습니다.

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

    reformatString(myString, function.name);
}

필자의 예제는 함수 이름에 대한 하드 코딩 된 검사를 사용하지만 switch 문이나 다른 논리를 사용하여 원하는 것을 쉽게 수행 할 수 있습니다.


나는 이것이 또한 크로스 브라우저 호환성 문제를 해결한다고 믿는다. 그러나 이것이 사실이라고 가정하기 전에 이것을 테스트하십시오! ( 땀을 흘리기 시작 )
GrayedFox

1

내가 아는 한, 우리는 이것과 같은 주어진 출처에서 2 가지 방법을 가지고 있습니다.

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

당신의 대답이 있다고 생각하십시오 :).


이것은 수년 동안 사용되지 않으며 Function.caller는 엄격 모드에서 작동하지 않습니다.
Dan Dascalescu

1

위의 모든 솔루션이 로켓 과학처럼 보이는 이유 한편,이 스 니펫보다 더 복잡하지 않아야합니다. 이 사람에 대한 모든 크레딧

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)]

3
이것이 내가 이것을 사용하여 얻는 것입니다 : TypeError : 'caller', 'callee'및 'arguments'속성은 엄격 모드 함수 또는 호출을위한 인수 객체에서 액세스 할 수 없습니다. 엄격 모드 에서이 작업을 수행하는 방법에 대한 아이디어가 있습니까?
hard_working_ant

1

이 질문으로 질문과 현재 현상금을 모두 해결하려고합니다.

현상금은 발신자를 엄격 모드 로 가져와야하며이를 볼 수있는 유일한 방법은 외부에서 선언 된 함수를 참조하는 것입니다 은 엄격 모드 에서 .

예를 들어, 다음은 비표준이지만 다음 버전 (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();


해킹은 좋지만 완전히 엄격한 모드 인 ES5 모듈에서는 작동하지 않습니다 .
Dan Dascalescu

0

어떤 이유로 든 기능이 정말로 필요하고 브라우저 간 호환이 가능하고 엄격한 것들에 대해 걱정하지 않고 앞으로 호환되도록하려면 다음 참조를 전달하십시오.

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
}

0

다음 코드가 도움이 될 것이라고 생각합니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.