Flow.js Ver 1.0.1 リリース と (this.self || global) の解説
Flow.js Version 1.0.1 をリリースしました。
使い方はこちらをごらんください
http://www.slideshare.net/uupaa/flowjs
リポジトリはこちらです
https://github.com/uupaa/flow.js
$ npm install flow_js でもインストールできます
既にインストールしている方は、
$ npm update flow_js でupdateできます。
主な改善は、
- FlowのargsをJunctionに引き継いでいなかったので引き継ぐようにしました
var Flow = require("flow_js").Flow; var junction = new Flow(2, function(err, args) { // この場合の args は = [ [1,4], [2,3] ] です。 // Array.prototype.concat.apply([], args).sort() で、 平滑化し [1,2,3,4] として取り出します var values = Array.prototype.concat.apply([], args).sort(); console.log(values); // -> "1,2,3,4" }); new Flow(2, junction).pass(1).pass(4); new Flow(2, junction).pass(2).pass(3);
- Junction(合流)はあるが、fork(分岐)機能がなかったため実装しました
var Flow = require("flow_js").Flow; // Date.now() % 2 の 結果により o_o または o_O に分岐します var flows = { o_o: function() { console.log("o_o"); }, o_O: function() { console.log("o_O"); } }; var flow = new Flow(2, flows); Date.now() % 2 ? flow.fork("o_O").pass() : flow.fork("o_o").pass();
- global.Flow がある場合は上書きしないようにしました
// Flow.js version 1.0.0 (function(global) { // --- export ---------- if (typeof module !== "undefined") { module.exports = { Flow: Flow }; } global.Flow = Flow; })(this.self || global);
// Flow.js version 1.0.1 (function(global) { // --- export ---------- if (typeof module !== "undefined") { // is modular module.exports = { Flow: Flow }; } global.Flow || (global.Flow = Flow); // 既に global.Flow があったらエクスポートしない })(this.self || global);
ソースコード末尾の (this.self || global) について
// Flow.js version 1.0.1 (function(global) { // --- header ---------- function Flow() {} // --- export ---------- if (typeof module !== "undefined") { // is modular module.exports = { Flow: Flow }; } global.Flow || (global.Flow = Flow); })(this.self || global);
結論
結論から先に言うと、
「(this || global) ではなく (this.self || global) としているのは、node.js でショートハンドできるから」です。
まず
Flow.js が node.js で動作するときは、(this.self || global) は (undefined || global) と評価されます。
ブラウザで動作するときは、(this.self || global) は (window || undefined) と評価されます(ブラウザ では window.self === window です)。
WebWorkersで動作するときは、(this.self || global) は (WorkerGlobalScope || undefined) と評価されます。
node, browser, webworker などの多様な環境で動作するコードを書くには、これが基本の形になるのかな? と思っています。
(ε・◇・)з o O ( ボクが勝手に言ってるだけです
次に
global.Flow = Flow; を行うことで、グローバル空間に、Flow がエクスポートされます。
ブラウザには require() がないため、global.Flow = Flow; が必須です。
また、node.js 環境では、global.Flow = Flow; があることで、
var Flow = require("flow_js").Flow; とせず、require("flow_js"); とタイプするだけで global.Flow が利用可能になります。
「node環境では、global.Flow = Flow; とすると、global空間に自動的にエクスポートされるが、これが悪さをするケースは(実際には)ほとんどないだろう」「ちょっと試したい時に、短く書ける方法があっても良いのでは」と考えました。
(ε・◇・)з o O ( 業務用途なら、ちゃんと var Flow = require("flow_js").Flow; って書いてくださいね
var self = this; が いけてない理由
ブラウザでは window.self は実質的に予約語です(ESの予約語一覧にはのってないけど)。
WebWorkers だと self は予約語です。
そのような状態ですので、node.jsとブラウザで両刀なjsを書こうとしたら node.js においても self という変数名の利用は好ましくない習慣といえます。
that を使いましょう。
// BAD var self = this; function hoge() { self.foo(); }
// GOOD var that = this; function hoge() { that.foo(); }