TypeScriptとKnockout.jsを組み合わせる際の注意点(thisの扱いについて)
TypeScript + Knockout.js
TypeScriptとKnockout.js(ES5)を組み合わせた場合のサンプルは以下を参照してください。
上記の記事では、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 }); } ... }
TypeScriptのenumをfor-in文で使用した時の挙動について
はじめに
最近Cordova+TypeScriptでハイブリッドアプリを作っているのですが、列挙型をfor-inしたときにハマったのでメモ。
現象
試しにこんなプログラムがあったとして
enum Hoge { Foo, Bar } for(var hoge in Hoge) { console.log(hoge); }
こう出力されてほしいのですが
Foo Bar
実際はこう出力されます
0 1 Foo Bar
解説
何でこんな挙動になるか調べたら下記にヒットしました。
enumをjavascriptにコンパイルすると
var Hoge; (function (Hoge) { Hoge[Hoge["Foo"] = 0] = "Foo"; Hoge[Hoge["Bar"] = 1] = "Bar"; })(Hoge || (Hoge = {});
と変換されるため、Hogeオブジェクトは以下となります。
Object {0: "Foo", 1: "Bar", Foo: 0, Bar: 1}
これによって、以下のように列挙型の値から文字列を取得したり、逆に文字列から列挙型の値を取得できるようになるわけですが、これのせいでfor-inが想定した結果を出力してくれないのです。
console.log(Hoge[0]) // "Foo" console.log(Hoge[Hoge.Foo]) // "Foo" console.log(Hoge["Bar"]) // 1
解決策
要はキーまたは値のうち、取りたくないほうを無視すればいいわけなので、stackoverflowでも示されている通り
文字列を取得したい場合
for(var key in Hoge) { if(!isNaN(key)) { console.log(key); } }
列挙型の値を取得したい場合
for(var value in Hoge ){ if(isNaN(value)) { console.log(value); } }
とすればOKです。それぞれ出力結果は
0 1
Foo Bar
となります。また、
TypeScript クイックガイド - phyzkit.net
にも書いてありますが、for文で繰り返すか、linq.jsのEnumerable.RangeToを使う手もあります。こっちの方がすっきりしますが、列挙型の値を自分で設定している、かつ、値に欠番がある場合は使えないので注意が必要です。
for(var i: Hoge = Hoge.Foo; i <= Hoge.Bar; i++){ console.log(Hoge[i]); }
Enumerable.RangeTo(Hoge.Foo, Hoge.Bar) .ForEach(x => { console.log(Hoge[x]); });
neocomplcacheからneocompleteへの乗り換え
はじめに
vimの環境整備をしていてneosnippetを入れたところ、スニペットの入力補完としてneocomplcacheを入れたはいいが、こちらはすでに更新を行わないらしい。ということでneocompleteを入れることにしました。
現状の確認
早速luaオプションが有効かどうか確認。
# vim --version | grep lua +listcmds +localmap -lua +menu +mksession +modify_fname +mouse -mouseshape
私のMacにデフォルトでインストールされているvimには入っていないみたいです。
ということで、vimを再インストールして上の出力結果にある-luaを+luaにするところから始めます。
vimをインストール
インストールオプションの確認
Macの場合はBrewでインストールできるので楽ちん。インストールする前にオプションを確認。
# brew options vim | grep lua 7:--with-lua 8: Build vim with lua support 9:--with-luajit 10: Build with luajit support
7行目の--with-luaオプションを使用すればOK。
他にも、後で必要になったときにまた再インストールするのが面倒なので--with-python3のオプションも有効にすることに。
インストール
調べたオプションを使用してvimをインストール。
システムで使用してるvimを別にインストールすると設定が面倒そうなので、今回は、--override-system-viを使用して既存のviを上書きしました。
# brew install vim --override-system-vi --with-lua --with-python3
完了したらターミナルを再起動すればインストールしたvimが使えるようになります。
改めてvimのオプションを確認すると
# vim --version | grep lua +dialog_con +lua +rightleft +windows
neocompleteの導入
あとはvim上で
- NeoBundleClean
- NeoBUndleInstall
をすればneocomplcacheが削除されてneocompleteがインストールされます。
プロキシ環境でrbenvを使ってrubyをインストールする
エラー内容
# rbenv install 2.1.5 Downloading ruby-2.1.5.tar.gz... -> http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.5.tar.gz error: failed to download ruby-2.1.5.tar.gz BUILD FAILED (CentOS release 6.5 (Final) using ruby-build 20150130-2-g8106d8f)
多分プロキシのせいだろうと思って調べたら下記がヒット
解決までの流れ
curlとwgetのプロキシ設定を変更
以下を実行してプロキシ設定を追加
# echo 'proxy = "https://proxy.hogehoge.net:8080/"' >> ~/.curlrc
# echo 'http_proxy = http://proxy.hogehoge.net:8080/' >> /etc/wgetrc # echo 'https_proxy = https://proxy.hogehoge.net:8080/' >> /etc/wgetrc
httpsはいらなかったかもしれないです。
コマンドオプションを変更
プロキシ設定の変更だけではだめだったので、ruby-buildの中身を見てみた。
# vi /root/.rbenv/plugins/ruby-build/bin/ruby-build
http_head_curl() { curl -qsILf "$1" >&4 2>&1 } http_get_curl() { curl -q -o "${2:--}" -sSLf "$1" }
調べてみると、curlの-qオプションは指定するとcurlrc設定ファイルが読み込まれないとのこと。ということで以下のとおり-qオプションを除外する。
http_head_curl() { curl -sILf "$1" >&4 2>&1 } http_get_curl() { curl -o "${2:--}" -sSLf "$1" }
再度rbenvを実行
[root@SVT6360314547 ~]# rbenv install 2.2.0 Downloading ruby-2.2.0.tar.gz... -> http://dqw8nmjcqpjn7.cloudfront.net/7671e394abfb5d262fbcd3b27a71bf78737c7e9347fa21c39e58b0bb9c4840fc Installing ruby-2.2.0... Installed ruby-2.2.0 to /root/.rbenv/versions/2.2.0
うまくいった!
ブログはじめました
はじめに
開発系でやってみたことや、忘れたくないことをまとめておきたいなぁという思いがあったので、アウトプットの練習も兼ねてブログを始めることにしました。
更新頻度は低めで、ゆるくやっていきたいとおもいます。よろしくお願いします。