以前書いた が基本的にはこう書けば良い:
var log = console.log.bind(console);
log('hoge: %s', 'fuga');
// => hoge: fuga
今回はこれに IE8+ 対応を加えたものについて書く。
イマイチな例
可変長引数を残しつつ bind
使わずにこう書く:
var log = function() {
var args = Array.prototype.slice(arguments);
console.log.apply(console, args);
};
これをやると、Google Chrome の開発者ツールのログ出力の右端にでる ファイル名:行数
の表示が常に apply
の場所になってしまうのでイマイチ。
少し関係ないけれど Array.prototype.slice(arguments)
のように arguments
を他所のスコープに持って行くと V8 エンジンの最適化を殺すことになるらしい。このあたりは実感ないので若干扱いに困ってる。
IE8+ 対応
今回は IE8+ で動作確認済みの例:
var log = (function(){
if (!(console && console.log)) {
// IE8-9 は開発者ツールを閉じると console が無くなるので諦める
return function() {};
}
if (!console.log.bind) {
// bind が使えないケース(IE8-9など)では apply を使う。
return function() {
var a = Array.prototype.slice.call(arguments);
Function.prototype.apply.call(console.log, console, a);
};
}
// IE10+ ではこれが使われるはず
return console.log.bind(console);
})();
先ほどの「イマイチな例」でダメだと言われていた slice
を使っているけれど、ここの処理は V8 では動かないはずなのでこれでいいかなーという感じ。
Function.prototype.apply.call(...)
のようにややこしく、console.log.apply
を直接使わない理由は、そもそも IE10 以前では console.log
が Function じゃないため __apply
を持っていない__から。。。
typeof console.log
// => "object"
typeof console.log.apply
// => "undefined"
コード中に書いてあるとおり console
が消えるので、短く書ける以外にも Polyfill 的な意味も含まれている。
はーIE滅んで欲しい。