Быстро и грязно в браузерах на базе Gecko:
new Error().stack
Вы также можете вручную тралить часть стека, используя Function.prototype.caller:
var thisFunction = arguments.callee;
var caller = thisFunction.caller;
var callerCaller = caller.caller;
// ...and eventually, assuming no recursion:
var bottomCaller = ...;
assert(bottomCaller.caller === null);
Одно (возможно, большое) предостережение от трюка .caller заключается в том, что он не обрабатывает рекурсию - .caller
смотрит сверху вниз на стек, чтобы найти первый экземпляр функции в стеке, а затем возвращает ее непосредственный абонент, поэтому, не проявляя осторожности, вы можете зацикливаться на бесконечном поиске абонентов.
Еще одна оговорка к caller
заключается в том, что в дальнейшем, если какой-либо ваш код использует строгий режим ECMAScript 5, свойство caller
функций строгого режима (или функций, которые сами были вызваны из функций строгого режима) так называемая «таблетка с ядом», которая выбрасывает TypeError
при доступе. Свойство caller
«связанных» функций (созданных методом ES5 Function.prototype.bind
) также является ядом. Эти ограничения нарушают общий алгоритм обхода стеков, хотя можно представить способы обхода этого, зависящие от использования (возможно, функции аннотирования входа и выхода).
Обратите внимание, что подобная обработка стека не является хорошей идеей в производственном коде (как быстрый взлом для отладки, это хорошо, правда); на данный момент обход стека, как в последнем примере, несколько дорог в движке Mozilla JS, и он, вероятно, выбросит вас из машинного кода и вернет в интерпретируемый код. Кроме того, обход стека O (n 2 ), что может иметь значение, если вы склонны иметь сложные глубокие стеки.