自分の速さで

調べたこと、忘れそうなことをゆるゆると書いていく

TypeScriptとKnockout.jsを組み合わせる際の注意点(thisの扱いについて)

TypeScript + Knockout.js

TypeScriptとKnockout.js(ES5)を組み合わせた場合のサンプルは以下を参照してください。

kojs.sukobuto.com

上記の記事では、JavaScriptの問題児thisと、その解決法としてFunction.bindによるthisの束縛を提案しています。
これには別の解決法もあるので、メモ。

アロー関数式

TypeScriptにおいて、関数の表現の仕方は以下の2つあります。

  • function式
  • アロー関数式

どちらも関数を表すものですが、アロー関数式はthisの扱い方が異なります。

アロー関数式を使用すると、以下のようなJavaScriptに変換されます。

TypeScript
class hogeClass {
    message: string;

    constructor() {
        this.message = "Hello, World!";
    }

    start() {
        setTimeout(() => { alert(this.message); }, 3000);
    }
}
JavaScript
var hogeClass = (function () {
    function hogeClass() {
        this.message = "Hello, World!";
    }
    hogeClass.prototype.start = function () {
        var _this = this;
        setTimeout(function () { alert(_this.message); }, 3000);
    };
    return hogeClass;
})();

アロー関数内におけるthisは、_thisを参照するように変換してくれるので、関数の呼び出し元に関係なく、インスタンスを参照します。これでthis問題が一気に解決します。

サンプルもこのように書けばbindなしでも動きます。

class GiftSetViewModel {
    constructor(public gifts: ItemViewModel[]) {
        ko.track(this); // プロパティ (gifts) を監視できるようにする
    }

    addGift = () => {
        this.gifts.push({
            name: "",
            price: 0
        });
    }

    ...
}