最近、こういうコードを見ておったまげた
incarnatePromise()
.then(console.log)
.catch(console.error);
ary.forEach(console.log);
何におったまげたかというと、 「console.log
をそのまま関数として扱ってる」 という点ですね。端的に書くと以下のようになります。
// (普通)メソッドとして扱う (this = console)
console.log("Hello")
// (おったまげ)関数として扱う (this = undefined)
const {log} = console
log("Hello")
// ↑は要するにこれ
(console.log)("Hello")
これ、以前だったら動く保証はありませんでした。実際になにかのブラウザでエラーになってました。
console.log
を関数として扱いたいなら、厳密にはこういうふうにする必要があるはずです。
// this を console に固定
const log = console.log.bind(console)
console.log の this が不要な処理系
じゃあ今、どのブラウザが this が undefined
な console.log
に対応しているかというと、手元にあるものを調べた感じ、全部いけるようです。
// テストコード
(console.log)("Hello") // => "Hello"
- Google Chrome (Edge Chromium) 100.0.x: OK
- Firefox 99.0.1: OK
- Safari 15.4: OK
- IE 11: OK
Node.js も見てみましょう。
- Node.js 4.0.0: OK
- Node.js 5.3.0: OK
- Node.js 9.11.0: OK
- Node.js 17.9.0: OK
Node.js には内部的に Consoleクラス があり、それ自体は this は必須なんですが、 global.console
については this が不要になるようにしている ようです。
そもそも私の思い違いか?
私の思い違いかと思ってネットを検索してみたところ StackOverflow で似たような質問があったので思い違いでは無いようです。
- console.log() called on object other than console
- Uncaught TypeError: Illegal invocation in JavaScript
昔のGoogle Chromeではどうやら (console.log)("Hello")
は動かなかったようですね。
今のブラウザ環境を前提にするのであれば、 console.log
をそのまま関数として扱っても実害は少なさそうです。