web-dev-qa-db-ja.com

「console.log」を安全にラップする方法は?

正当な生産上の理由、たとえば単体テストハーネスのようなもののために、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を使用して引数を実際の配列に変換するのと同じハック。

これは、私のchromeコンソールでうまく機能します。

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を安全にラップするための合理的なアプローチですか?]


その他の質問

以下のnavの回答のリンクをたどると、コードが表示されます。

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

この場合、argumentsを配列に変換する目的は何ですか?これを行わないと、一部のブラウザで失敗するはずです。そして、opera奇妙な振る舞いとコンソールレスブラウザは別として、このようなものは他のすべてのブラウザでも同様に動作するはずではありませんか?prototypeは上記の例、または私たちはただつまらない... Function.call.callまたはObject.call.callまたはその点でisNaN.call.callFunction.prototype.call.callと同様に機能するようです。

47
Dagg Nabbit

IEでこのログ関数を正常に呼び出すことはできますが、ここでapplyを使用すると、それが可能であることを示すことができますか?

はい、そしてはい。この特定の例は、リンクされた質問の"is it real function"の部分を真っ直ぐに狙ったものです。

そして、リンクされた質問から、IEのコンソールが実行中に閉じられた場合、これは失敗するので、コンソールが開いた後でもログが機能しないと思いますか?

正しい。その質問に対する私の答えで説明したように、consoleオブジェクトは、特定のタブの開発者ツールが初めて開かれるまで公開されません。ほとんどの開発者はコンソールシムを使用します。その場合、Function#bindアプローチは、Function#apply.apply 方法。

この場合、引数を配列に変換する目的は何ですか?

ありません、それは冗長です。カスタムlog実装でない限り、その場合、開発者は引数オブジェクトを配列に変換する理由があるかもしれません。

そして、プロトタイプは上記の例で目的を果たしますか、それとも私たちはただの教育的です...

はい、そうです。一部の開発者は、無意識のうちにFunction.callカスタム関数または値。もちろん、_Function.prototype.callも、しかしこれは偶然に起こる可能性がはるかに低いです。

7
Andy E

ラッパーの問題は、ログメッセージのソースのファイル名と行番号を難読化することです。

他のブラウザーの行番号を保持する単純なIE7以下のシム:

/* console shim*/
(function () {
    var f = function () {};
    if (!window.console) {
        window.console = {
            log:f, info:f, warn:f, debug:f, error:f
        };
    }
}());
20
dbrin

申し訳ありませんが、私の投稿にバグがありました。どうして見逃したかわかりません。

グローバルコンソールオブジェクトを作成する適切な方法(存在しない場合):

if (typeof console === "undefined"){
    console={};
    console.log = function(){
        return;
    }
}
16
ChrisN

私は使用したい:

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

すべてのブラウザで動作し、理解しやすいです。

6
etoxin

以下のコードスニペットを使用してみてください...(これは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");
3
Ammar Hasan

クリスの答えのわずかなバリエーションとして、空の関数を持つ「コンソール」のプロパティとして「ログ」を定義するだけです。

if (typeof console === "undefined") {
    console = {
        log: function () {
            return;
        } 
   };
}
1
dougajmcdonald

Paul Irishには、console.log()のNice light wrapper/replacementがあります。

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

利点:

  • コンソールが近くにない場合のエラーを防ぐ(つまりIE)
  • ログの履歴を保持するため、後でコンソールが追加された場合に過去を確認できます(例:firebug lite)
  • 軽くてシンプル。
  • log()またはwindow.log()のようにすばやく入力できます。
0
Thomas W

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

js:

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

慰めを使う

私の途方もなく過剰に設計されたコンソール:

  • コンソールがない場合にエラーを防ぎます
  • コードにconsole.logステートメントを残した場合、本番環境でのログインを防止します
  • console.errorconsole.group、およびそのような他のすべてのメソッドをサポートします
  • ログステートメントへのバックトレースを引き続き提供します

すごい。

しかし、実際には、コードにconsoleステートメントを置いたままにしないでください。

見よ、震え!提示: Consolation.js

0
Nathan Long