きみはねこみたいなにゃんにゃんなまほう

ねこもスクリプトをかくなり

(0, obj.method) は this の参照を obj から外せるらしい

Hyperapp を始めようとしたら Parcel という Webpack がシンプルになったようなツールがあるのを知り、バンドルされたコードを見てみたら

var _hyperapp = require("hyperapp");

(0, _hyperapp.app)({
  view: function view(state) {
    return (0, _hyperapp.h)('div');
  }
});

という表現があり、初見では (0, _hyperapp.app) どう評価されるのかが分からなかったので少しだけ試したり調べたりしました。

挙動は多少わかった気がしますが、この表現が必要な理由までは読み解けませんでした。

, オペレータ

node の REPL で確認したところ , はどうやら最後の値を返すようです。

(0, 1) // => 1
(0, 1, 2, 3) // => 3
('this', 'is', 'a', 'pen') // => 'pen'

つまり

(0, _hyperapp.app) // => _hyperapp.app

ということですね。これだけだと何の意味もないワンクッションに見えるのですが、これにより this の参照が変わるみたいなのです。

https://stackoverflow.com/questions/40967162/what-is-the-meaning-of-this-code-0-function-in-javascript

のコメントを見なければ気づけませんでした。

オブジェクトのメンバとしての関数の呼び出し方

とりあえず知っていることをおさらいしておくと、JavaScript ではオブジェクトが関数フィールドを持つ場合、その呼び出し方によって this の参照先が変わるという話があります。

単純な例として this を返す関数を持つオブジェクトがあって

const obj = { method() { return this } }

この obj.method の参照する関数をふた通りの方法で呼び出すことを考えてみると

// A
obj.method() // => global

// B
const method = obj.method
method() // => obj

obj.methodmethod も同じ関数を参照しているのに返ってくる this の値が異なりますね。

ハンドラとして obj.method 形式で関数を渡したのに this 云々なエラーが返ってきて、理由もわからないまま .bind(obj) でとりあえず想定通りの動きになった、というのは初心者によくあるパターンです。

StackOverflow のコメントを見るに、this の参照を obj から外したい場合に

const method = obj.method
method()

と書く代わりに

(0, obj.method)() // => global

と書くことができて楽、ということなのでしょうか。

Parcel が何のためにこういうことをしているのか読み解くのが先ですね。今日はここまでにします。

追記

AST Explorer で確認してみたところ SequenceExpression という評価式らしいです。しかし ECMA Script Specification にはこの表現は見つかりませんでした。