TypeScriptで'this'のエイリアスはあるのか?
質問
TypeScriptで、jQueryのイベントに対するイベントハンドラーコールバックとして動作するメソッドを定義したクラスを書こうとしています。
class Editor {
textarea: JQuery;
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin(onFocusIn);
}
onFocusIn(e: JQueryEventObject) {
var height = this.textarea.css('height'); // <-- This is not good.
}
}
onFocusInイベントハンドラ内で、TypeScriptは'this'をクラスの'this'であるとみなしています。しかし、jQueryはthis参照をオーバーライドし、イベントに関連付けられたDOMオブジェクトに設定します。
この場合、TypeScriptは隠された_thisエイリアスを持つ一種のクロージャを作成します。
class Editor {
textarea: JQuery;
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin((e) => {
var height = this.textarea.css('height'); // <-- This is good.
});
}
}
私の質問は、このjQueryの動作を克服するために、TypeScriptを使用してメソッドベースのイベントハンドラ内でこの参照にアクセスする別の方法はありますか?
どのように解決するのですか?
このように、TypeScriptにはメソッドを常にその
this
ポインタに常にバインドされていることを保証する TypeScript のメカニズムは存在しない(そしてこれは jQuery だけの問題ではない)。 必要なのは、メソッドのプロキシを生成し、そのプロキシが
this
ポインタを復元するプロキシを生成することです。それから、イベントに渡す前に、そのプロキシでコールバックをラップする必要があります。
jQuery.proxy()
. このメソッドを使用した上記のコードの例です (追加された
$.proxy()
の呼び出しに注目してください)。
class Editor {
textarea: JQuery;
constructor(public id: string) {
this.textarea = $(id);
this.textarea.focusin($.proxy(onFocusIn, this));
}
onFocusIn(e: JQueryEventObject) {
var height = this.textarea.css('height'); // <-- This is not good.
}
}
これは合理的な解決策だが、個人的には開発者がプロキシ呼び出しを含むことをしばしば忘れることに気づいたので、この問題に対するTypeScriptベースの別の解決策を思いついた。 使用するのは
HasCallbacks
からクラスを派生させるだけでよい。
HasCallbacks
を継承し、接頭辞に
'cb_'
で始まるメソッドには
this
のポインタは永久に束縛されます。 そのメソッドを別の
this
ポインタを持つメソッドを呼び出すことができないだけで、ほとんどの場合はその方が望ましいのです。 どちらのメカニズムも機能するので、使いやすい方を選択すればよいのです。
class HasCallbacks {
constructor() {
var _this = this, _constructor = (<any>this).constructor;
if (!_constructor.__cb__) {
_constructor.__cb__ = {};
for (var m in this) {
var fn = this[m];
if (typeof fn === 'function' && m.indexOf('cb_') == 0) {
_constructor.__cb__[m] = fn;
}
}
}
for (var m in _constructor.__cb__) {
(function (m, fn) {
_this[m] = function () {
return fn.apply(_this, Array.prototype.slice.call(arguments));
};
})(m, _constructor.__cb__[m]);
}
}
}
class Foo extends HasCallbacks {
private label = 'test';
constructor() {
super();
}
public cb_Bar() {
alert(this.label);
}
}
var x = new Foo();
x.cb_Bar.call({});
関連
-
[解決済み】Typescriptで、! (エクスクラメーションマーク/バン)演算子でメンバを再参照するのは?
-
[解決済み] jQueryでチェックボックスに "checked "を設定する
-
[解決済み] jQueryの「exists」関数はありますか?
-
[解決済み] セレクタの子を取得する方法は?
-
[解決済み] Microsoft JSONの日付はどのようにフォーマットするのですか?
-
[解決済み] TypeScriptで文字列を数値に変換する方法とは?
-
[解決済み] TypeScript で `window` に新しいプロパティを明示的に設定するにはどうすればよいですか?
-
[解決済み] TypeScriptでの取得と設定
-
[解決済み】TypeScriptのインターフェースと型について
-
[解決済み] TypeScriptのプライベートな「関数
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
echarts-all.js:1 Uncaught TypeError: nullのプロパティ'getAttribute'を読み取ることができません。
-
[解決済み] jQueryのpreventDefault()が発動しない
-
[解決済み] jQueryで複数のクラスを持つ要素を選択するにはどうすればよいですか?
-
[解決済み] JQueryでラジオボタンがチェックされているかどうかを調べる?
-
[解決済み] jQuery UI DatePicker - 日付フォーマットの変更
-
[解決済み] jQueryでloading spinnerを表示するには?
-
[解決済み] JSONPとは何か、素人目にもわかるように説明してくれる人はいませんか?[重複)。
-
[解決済み] jQuery .onとhoverの使い分けは可能ですか?
-
[解決済み] jQuery OR Selector?
-
TypeScriptはクラスに対するイベントをサポートしていますか?