Как безопасно обернуть `console.log`? - PullRequest
47 голосов
/ 09 января 2012

Предположим, я хочу включить некоторые вызовы на console.log по какой-то законной производственной причине, скажем, что-то вроде жгута модульного тестирования. Очевидно, я бы не хотел, чтобы это выдавало преждевременное исключение, если в браузере нет console или если отсутствует консоль .

Какой лучший способ создать простую log функцию для записи материалов на консоль или без вывода сообщений об ошибках, если консоли нет?

Принятый ответ на вопрос, указанный выше:

var log = Function.prototype.bind.call(console.log, console);
log.apply(console, ["this", "is", "a", "test"]);

Может ли эта log функция нормально вызываться в IE, и использование apply здесь просто для того, чтобы показать, что это возможно? И я предполагаю из связанного вопроса, что это потерпит неудачу, если консоль IE будет закрыта при запуске, поэтому log не будет работать даже после открытия консоли, правильно? Если это не так, может кто-нибудь объяснить, как это работает?

Эта статья ycombinator представляется актуальной. Они говорят о том же поведении IE, что и вопрос, связанный выше?

Function.prototype.apply.apply(console.log, [console, arguments]);

Работает как на IE9 неработающий console.log, так и на обычном console.log других производителей. Тот же хак, что и при использовании Array.prototype.slice для преобразования аргументов в реальный массив.

Это хорошо работает в моей хромированной консоли.

function echo(){
  Function.prototype.apply.apply(console.log, [console, arguments]);
}

Упрощенная:

function echo(){
  Function.apply.call(console.log, console, arguments);
}

Добавить чек и вернуть:

function echo(){
  return window.console && console.log &&
         Function.apply.call(console.log, console, arguments);
}

Пример выше выглядит адекватным для меня. У меня нет IE под рукой, чтобы проверить его, хотя. Это разумный подход для безопасной упаковки console.log?


Дополнительные вопросы

Переходя по ссылке в ответе ниже, мы видим код:

Function.prototype.call.call(console.log, console,
    Array.prototype.slice.call(arguments));

Какова цель преобразования arguments в массив в этом случае? Я полагаю, что в каком-то браузере произойдет сбой, если вы этого не сделаете? И, кроме странного поведения оперы и браузеров без консоли, разве что-то подобное не должно работать в любом другом браузере? И служит ли prototype цель в приведенных выше примерах, или мы просто педантичны ... Function.call.call или Object.call.call, или в этом отношении isNaN.call.call, кажется, работает так же хорошо, как Function.prototype.call.call.

Ответы [ 10 ]

20 голосов
/ 17 июня 2013

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

Простая оболочка IE7 и ниже, которая сохраняет нумерацию строк для других браузеров:

/* console shim*/
(function () {
    var f = function () {};
    if (!window.console) {
        window.console = {
            log:f, info:f, warn:f, debug:f, error:f
        };
    }
}());
16 голосов
/ 22 июля 2012

Извините, в моем сообщении была ошибка.Не знаю, как я пропустил это.

ПРАВИЛЬНЫЙ способ создания объекта глобальной консоли, если он не существует:

if (typeof console === "undefined"){
    console={};
    console.log = function(){
        return;
    }
}
7 голосов
/ 09 января 2012

Может ли эта функция журнала нормально вызываться в IE, и использование apply здесь просто для того, чтобы показать, что это возможно?

Да и да.Этот конкретный пример был нацелен прямо на «это реальная функция» часть связанного вопроса.

И я предполагаю из связанного вопроса, что это не удастся, если IEконсоль закрывается при запуске, поэтому журнал не будет работать даже после открытия консоли, верно?

Правильно.Как объяснялось в моем ответе на этот вопрос, объект console не открывается до тех пор, пока инструменты разработчика не будут открыты для конкретной вкладки.Большинство разработчиков используют консольную прокладку, и в этом случае подход Function#bind становится немного устаревшим, потому что вы также можете использовать метод Function#apply.apply.

Какова цель преобразования аргументов в массивв этом случае?

Нет ни одного, это избыточно.Если это не пользовательская реализация log , в этом случае у разработчика может быть причина для преобразования объекта аргументов в массив.

И прототип служит цели в вышеприведенных примерахили мы просто педантичны ...

Ну да, и нет.Некоторые разработчики могли невольно изменить Function.call на пользовательскую функцию или значение.Конечно, они тоже могут сломаться Function.prototype.call, но это гораздо реже случится случайно.

6 голосов
/ 21 июня 2013

Мне нравится использовать:

'console' in window && console.log("Boom!");

Он работает во всех браузерах и прост для понимания.

3 голосов
/ 18 февраля 2014

Попробуйте использовать фрагмент кода ниже ... (это мой предпочтительный подход, потому что он делает вас независимым от window.console)

var logger = (function (c) {
    "use strict";
    var m = {
        log: function (a, t) {
            if (!c) { return; /* return or call your custom function here */ }
            var l = c.log,
                f = t === undefined ? l : (this.__dict__[t] || l);
            f.apply(c, a)
        },
        __dict__: {
            "trace": c.trace,
            "debug": c.debug,
            "info": c.info,
            "warn": c.warn,
            "error": c.error
        }
    };

    return {
        trace: function () { m.log(arguments, "trace"); },
        debug: function () { m.log(arguments, "debug"); },
        info: function () { m.log(arguments, "info"); },
        warn: function () { m.log(arguments, "warn"); },
        error: function () { m.log(arguments, "error"); },
        log: function () { m.log(arguments, undefined); }
    };
}(window.console))

Теперь вы можете попробовать это в своем коде и увидеть результат

logger.info("Hello");
logger.trace("Hello");
logger.debug("Hello");
logger.warn("Hello");
logger.error("Hello");
logger.log("Hello");
1 голос
/ 08 августа 2012

В качестве небольшого варианта ответа Криса просто определите «log» как свойство «console» с пустой функцией:

if (typeof console === "undefined") {
    console = {
        log: function () {
            return;
        } 
   };
}
0 голосов
/ 22 января 2017

CoffeeScript:

empty_function = ->
  return
if !window.console?
  window.console = {}
  for fn in ['log', 'info', 'warn', 'debug', 'error']
    if (typeof window.console[fn] isnt 'function')
      window.console[fn] = empty_function

ЯШ:

(function() {
  var empty_function, fn, i, len, ref;

  empty_function = function() {};

  if (window.console == null) {
    window.console = {};
    ref = ['log', 'info', 'warn', 'debug', 'error'];
    for (i = 0, len = ref.length; i < len; i++) {
      fn = ref[i];
      if (typeof window.console[fn] !== 'function') {
        window.console[fn] = empty_function;
      }
    }
  }

}).call(this);
0 голосов
/ 28 августа 2013

Use Consolation

Моя смехотворно перегруженная консоль:

  • предотвращает ошибки при отсутствии консоли
  • запрещает вход в систему, если вы оставили операторы console.log в своемкод
  • поддерживает console.error, console.group и все другие подобные методы
  • по-прежнему дает вам возможность вернуться к вашим операторам журнала

Это удивительно.

Но на самом деле, вы не должны оставлять в своем коде console операторов.

Вот и дрожите!Представляем: Consolation.js

0 голосов
/ 02 мая 2013

У Пола Айриша есть приятная легкая оболочка / замена для console.log().

http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/

Преимущества:

  • Предотвращение ошибок, если консоль не 't вокруг (то есть IE)
  • Поддерживает историю журналов, так что вы можете посмотреть в прошлое, если ваша консоль будет добавлена ​​впоследствии (например, Firebug Lite)
  • Легкий и простой.
  • Очень быстро печатать - log() или window.log().
0 голосов
/ 06 февраля 2013

Мое решение немного отличается. Я создаю стандартный ярлык для всех вызовов console.log: в моем случае kag (все, что я хочу сообщить в консоли).

Я проверяю IE, если IE отправляю результаты в окно предупреждения. Если Chrome затем отображается в консоли. Это также означает, что IE всегда будет работать даже в закрытой консоли:

Код:

var iever = getInternetExplorerVersion();
if(iever>-1){
function kag(params){
    alert(params);
}
} else {
var kag = console.log.bind(console, "REPORT: ");
}

function getInternetExplorerVersion() {
var rv = -1;
if (navigator.appName == 'Microsoft Internet Explorer') {
var ua = navigator.userAgent;
var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
if (re.exec(ua) != null){
  rv = parseFloat( RegExp.$1 );
}
}
return rv;
}
...