ES6 (ES2015) で追加された WeakSet は、かなり使い方が限定された(≒ まだ有効な使い方があまり見つかっていない)コレクションクラスです。
Task.js では、この WeakSet を現在実行中のインスタンスの一覧を開発者に提示する Task.dump() 機能で利用していますので、その背景と使い方について軽く説明をしてみたいと思います。
Task.js が WeakSet を使って実装されたのはごく最近の事です。
初期の Task.js のデザインではこのようになっていました。
https://github.com/uupaa/Task.js/blob/1798bcd241b7ac9268d3e7eedd39b40ae5107d06/lib/Task.js
- 実行中のインスタンスを保持するコレクションクラスには Object を使用しています
- _taskCount にインクリメントする値を格納しています
- Object の key の衝突(上書き)問題を防ぐためにユニークな名前を生成(name + "@" + _taskCount)しています
var _taskInstances = {}; // instances. { "taskName@counter": TaskInstance, ... }
var _taskCount = 0;
function Task(...) {
this["name"] = name + "@" + (++_taskCount); // String: "task@1"
_taskInstances[this["name"]] = this; // register task instance.
}
Task["dump"] = Task_dump; // Task.dump(filter:String = ""):Object
Task["clear"] = Task_clear; // Task.clear():void
function _update(...) {
if (処理終了) {
delete _taskInstances[that["name"]]; // [!] GC
}
}
function Task_dump(...) {
return JSON.parse( JSON.stringify(_taskInstances) ); // dead copy
}
function Task_clear() { // @desc clear snapshot.
_taskInstances = {}; // [!] GC
_taskCount = 0; // [!] reset count
}ちょっと、ごちゃごちゃしてしまっていますね。
Version 1.0.0 以降ではこのようになっています。
https://github.com/uupaa/Task.js/blob/5f3c7bfa459500b773844955ae1186845fc454fb/lib/Task.js
- _taskInstances, _taskCount, Task.clear() を廃止しました
- Task.dump はインスタンスのスナップショット(WeakSet)を返すようにしました
function Task(...) {
Task.snapshot.add(this);
}
Task.snapshot = new WeakSet(); // { TaskSnapShot, ... }
Task["dump"] = function() { return Task.snapshot; }; // Task.dump():TaskSnapShotWeakSet
function _updateState(...) {
if (処理終了) {
Task.snapshot.delete(that); // [!] GC
}
}Task.dump が返す値は、静的なものではなく動的な値です。
インスタンス名を直接指定することでコンソールから操作を加える事も可能ですが、
その場で状況を確認する用途に特化しています。
また、不要になったインスタンスは自動的に消滅します。
このようなケースでは WeakSet はとても便利ですね。
TODO: 時間切れ。ざっくり書き過ぎなので、もうちょっと続き書く
ES.js をロードすると、WeakSet が存在しない環境でも動作します。
