Как узнать, вызывается ли функция из консоли или из исходного кода

Я хочу знать, есть ли способ проверить, вызывается ли функция javascript из консоли браузера или из исходного кода.

Я определил функцию, которая может проверить, из консоли или со страницы, но она работает только в google chrome, она не работает в firefox, я не тестировал другие браузеры

function fromConsole()
{
    var Caller = arguments.callee.caller;
    while(Caller.caller != null)
        Caller = Caller.caller;
    return (Caller.toString().indexOf("function (expression, objectGroup,"))!=-1;
}

как эта функция работает

эта функция ищет верхнюю функцию, которая вызвала нашу функцию. в google chrome определение верхняя функция, если она вызывается из консоли, содержит эту строку function (expression, objectGroup, в firefox нет функции

позвольте мне объяснить вам в деталях

предположим, у нас есть этот пример

function a()
{
    b();
}
function b()
{
    return c();
}
function c()
{
    console.log(fromConsole());
}

если мы вызываем функцию a () со страницы , она показывает в консоли false (потому что верхняя функция-a ()) однако, если мы вызываем ее из консоли, она показывает true, потому что верхняя функция-это "function (expression, objectGroup,..."

в firefox верхняя функция всегда a () если вы вызываете свою функцию из консоли или со своей страницы

у меня вопрос: есть ли способ узнать, вызывается ли функция из консоли или нет ?

3 ответов


в Chrome консоль всегда вызывает промежуточные функции JavaScript, в Firefox вызов поступает непосредственно из собственного кода. Как следствие, вы можете проверить arguments.callee.caller в Chrome, но в Firefox это всегда будет null. Safari ведет себя так же, как Firefox здесь, поэтому проверка вызывающего абонента-это действительно трюк, который работает только в Chrome.

то, что вы можете проверить, тем не менее Error.stack свойства. Следующая функция работает в Firefox, Chrome и даже Сафари:

function fromConsole()
{
    var stack;
    try
    {
       // Throwing the error for Safari's sake, in Chrome and Firefox
       // var stack = new Error().stack; is sufficient.
       throw new Error();
    }
    catch (e)
    {
        stack = e.stack;
    }
    if (!stack)
        return false;

    var lines = stack.split("\n");
    for (var i = 0; i < lines.length; i++)
    {
        if (lines[i].indexOf("at Object.InjectedScript.") >= 0)
            return true;   // Chrome console
        if (lines[i].indexOf("@debugger eval code") == 0)
            return true;   // Firefox console
        if (lines[i].indexOf("_evaluateOn") == 0)
            return true;   // Safari console
    }
    return false;
}

это будет идти вверх по стеку, пока не найдет запись, соответствующую консоль. Это значит, что fromConsole() не нужно вызывать напрямую, между ними может быть любое количество других вызовов функций. Тем не менее, его можно легко обмануть, например, с помощью setTimeout():

setTimeout(fromConsole, 0);

здесь вызывающий будет собственным обработчиком таймаута, ничего не указывая на консоль больше.


это кросс-браузерный способ увидеть, был ли он вызван из общедоступного (глобального, вызываемого консолью js) или частного (вашего кода) контекста:

(function() { 
    window.f = function() {
        console.log('public')
    } ;
    //f will be this function in the rest of the code in this outer function:
    var f = function() {
        console.log('private'); 
    }
    f();
    //more code here...

}) ()

код во внешней функции будет использовать функцию private во время выполнения f() из консоли будет запущена функция public.


для Chrome вы можете просто проверить, есть ли keys функция доступна. Это часть chrome API командной строки и доступен только тогда, когда код был выполнен с консоли

function myFunction() {
  var fromConsole = typeof keys === 'function' && keys.toString().indexOf('Command Line API') !== -1
  if (fromConsole) {
    alert('From console')
  } else {
    alert('Not from console')
  }
}