JavaScript の using と DisposableStack#defer で Go の defer 風
JavaScriptのExplicit Resource Managementという提案では using という構文が注目されがちな気がする。しかし実は構文以外にもいくつかのビルトインが追加される。
こないだExplicit Resource Managementで追加されたビルトインをSafariに実装したときに「へ〜」と思ったのでよくありそうな使い方を紹介する[1]。
Go の defer
Go の defer をご存知だろうか。たとえばこういうコードがあるとする。
func main() {
    f := createFile("/tmp/defer.txt")
    defer closeFile(f)
    writeFile(f)
}
main 関数内の2行目では defer closeFile(f) を実行している。ここで、この closeFile(f) は createFile の直後には呼び出されない。代わりにこのmain関数のスコープを抜ける時、つまりここでは writeFile(f) の直後に呼び出される。
defer を使うことでリソースの確保と解放をコード上の近い場所に書くことができる。
 JavaScript の using と DisposableStack#defer
JavaScriptでもExplicit Resouce Managementによって追加される using という構文と DisposableStack というビルトインを使うことによって、Goのdeferのようにリソースの確保と解放の処理を記述できる。
たとえば、こういうふうに書くことができる。
function main() {
    using stack = new DisposableStack();
    const f = createFile("/tmp/defer.txt");
    stack.defer(() => { closeFile(f); });
    writeFile(f);
}
このコードは前述したGoのdeferの例をそのままJavaScriptに移植したものだ。
まず main 関数の先頭で using 構文を使って DisposableStack のインスタンス stack を作る。こうすると main 関数のスコープを抜ける時に stack[Symbol.dispose] 関数が呼び出されるようになる。これは using 構文の機能である。
DisposableStack は内部にスタックを持つデータ構造だ。スタックのエントリはそれぞれ [Symbol.dispose] 関数を持つオブジェクトである[2]。そして DisposableStack 自体の [Symbol.dispose] 関数はスタック内の全てのエントリの [Symbol.dispose] 関数を呼び出す。
stack.defer(fn) は、 [Symbol.dispose] が呼び出された時に fn を呼び出すだけの disposable stack を新たに作成して stack の内部スタックに積む。
つまり、main 関数のスコープを抜ける時にはまず stack[Symbol.dispose] が呼び出される。その呼び出しによって stack の内部スタック内の全てのオブジェクトの [Symbol.dispose] が呼び出される。この時スタック内には () => { closeFile(f); } を呼び出すだけのオブジェクトが存在しているため、その関数が呼び出される。
このように using と DisposableStack を使うことでJavaScript においても Go の defer のようにリソースの確保と解放の処理を記述できる。
まとめ
- Go の 
deferを使うことでリソースの確保と解放をコード上の近い場所に置ける - JavaScript でも Explicit Resource Management 提案の 
using構文とDisposableStack#deferを使うと、似たように書くことができる 
Discussion
defer に非同期も混ぜるなら
AsyncDisposableStackもいいですよね。