Generatorとthis
Generatorがnode.jsではharmonyオプション付きですがバージョン11から使用できるようになりました。
generetorの説明は各所で行われているので省略します、今回はthisとの関係を調査しました。
調査
thisの束縛はbind,call,applyを使用します。
さらに今回はkoaフレームワークでお世話になるcoモジュールを使用した場合はどのようになるかを確認します
コードはnode --harmony this.js
で実行します
this.js
// 束縛対象
var self = {x: 1};
// ジェネレータ関数
// yieldが存在しないため、nextを一回実施しただけで処理が完了する意味ないものですが、
// thisの調査だけなので意味なくジェネレータ関数にしています
var generator = function * () {
'use strict';
if (this === global) console.log('this === global');
else if (this === self) console.log('this === self');
else if (this === void 0) console.log('this === undefined');
else console.log('this === ???');
};
var co = require('co');
var gn, g;
console.log('(1)');
g = generator();
g.next(); // this === undefined
console.log('(2)');
gn = generator.bind(self);
g = gn();
g.next(); // this === self
console.log('(3)');
g = generator.call(self);
g.next(); // this === self
console.log('(4)');
g = generator.apply(self);
g.next(); // this === self
console.log('(5)');
g = generator();
// g.next.call(self); // 例外発生
// g.next.apply(self); // 例外発生
console.log('(6)');
co(generator)(); // this === global
console.log('(7)');
gn = generator.bind(self);
// co(gn)(); // 例外発生
console.log('(8)');
co(generator).bind(self)(); // this === self
console.log('(9)');
co(generator).call(self); // this === self
console.log('(10)');
co(generator).apply(self); // this === self
まとめ
koaフレームワークのミドルウェアによってはthisの束縛を強要するものがありました。
試験的に動作させるにはどうしたら良いと思って確認してみたところ、面白いことが発見できました
5で確認できるように一度作成されたジェネレータ・イテレータのthisを途中で変更する事はできません
6のようにcoを普通に使用するとuse strict
にも関わらずglobalが設定されている点は注意が必要です。
7ではbindされたジェネレータ関数は普通の関数になってしまうのでcoの引数にする事はできなくなります