これ何?
タイトルを見てなんだこれはと思われた方もいらっしゃると思いますが
Babelでトランスパイルをしたコードを見ていると
import { b } from './a.js'
function c(n) {
return b(n)
}
var _a = require('./a.js')
function c(n){
return (0,_a.b)(n)
}
のようなコードが出てくる事が気になって調べた。
ちなみにBabelのREPL結果、presetsはenvのみ適用
ちょっと抽象的すぎるコードなので、 fn(args)
を実行した時との動作の違いがわかるようなコードを用意した。というかStackOverflowから引っ張ってきた。
var foo = {
fullName: "Peter",
sayName: function() { console.log("My name is", this.fullName); }
};
// もしくは単に、fullName = 'Shiny';
window.fullName = "Shiny";
foo.sayName(); // My name is Peter
(foo).sayName(); // My name is Peter
(foo.sayName)(); // My name is Peter
(0, foo.sayName)(); // My name is Shiny
ブラウザで実行してみた例↓
この例をみてわかるように、 (0, foo.sayName)()
以外で実行した時はfullName
は foo
オブジェクトにbindされているが、 (0, foo.sayName)()
の fullName
はグローバルオブジェクトにbindされている。
(2020/06/19追記: fooへのbindが解除されて結果、グローバル変数であるfullNameを参照する事になるとの事でした。@shiracamusさん、丁寧な解説ありがとうございました。)
ちなみに最初の数字は 0
以外でもいけるみたいだ。
何個でも0書いても結果は同じ
nullでもundefinedでもなんなら、fooオブジェクトでも、最後がfoo.sayNameなら実行できる
どうも右から左に評価されて最後に評価された結果を返すらしい。
活用事例
var a = 0,
b = 1,
c;
c = ( a++, b++, a + 2 ); // a is added, b is added, and a is added then returned
a; // 1
b; // 2
c; // 3
よく見る例としては、for文
for (i = 0, j = 42; i < 10; i++, j--) {}
i = 0
が評価されて、 j = 42; i < 10; i++
が評価されて、最後に j--
が評価されると見るらしい。
なるほど!
for文をこのように解釈したのは生まれて初めてかもしれない。
まとめ
しかし、なぜBabelはimportしたオブジェクトa
のプロパティー(関数) b
を実行する時に、bindをグローバルにするのかよく分かってない。
(2020/06/19追記。解決したのでコメント欄に書いております。@shiracamusさん、丁寧な解説ありがとうございました。)
テクニックの一つとして覚えておいたら役に立つ時がくるのかな?
Babelを学ぶとJavaScript力つくなこりゃ...
この記法について
(2020/06/20追記)
この (0, fn)(args)
は acorn
で調べたら、SequenceExpression
となっているので、 シーケンス式
と呼べるものだと思います。