问题
在 TS 里面 this
关键字一开始让我这个写 C# 的十分惊讶,比如下面的一段代码,注意 initBinding
方法
class Company {
id:number;
/**
* 在点击编辑按钮的时候开始初始化 currentCompany 对象
* @param e 触发事件的 tr
*/
constructor(e:JQueryEventObject) {
//省略了初始化字段的代码
this.initBinding();
}
/**
* 在这里绑定模态框的事件
*/
initBinding() {
$('#confirmDelete').one('click',this.confirmDelete);
}
/**
* 确认删除按钮的行为
* @returns {boolean} 删除是否成功
*/
confirmDelete():boolean {
console.log("确认删除"+this.id);
//省略请求服务器处理的操作
return true;
}
}
在 initBinding
方法里面,我给一个按钮的 click
事件绑定了一个方法,这个方法会打印一下当前选中的公司的 id
但是,结果让人意外,打印出来的竟然是这个按钮的 id
按照原先学习的 C# 里面面向对象的观念,对象的方法里面的 this
应该是指的这个对象本身,可是在这里的 this
却变成了触发事件的按钮。
分析
让我们想想 js 中是如何定义成员方法的,定义一个属性,属性的值是一个 function ;
所以,在我们调用的这个成员方法的时候实际上是调用的这个属性返回的方法,这个方法其实是与返回他的属性所属的对象是无关的。
换句话来说,成员方法中的 this
要结合调用它的上下文来看待,在上面的例子中,我们是在按钮的 click
事件中调用的 confirmDelete
方法,所以,其中的 this
就是指的这个产生 click
事件的按钮。
解决
为了让 confirmDelete
方法能够找到正确的上下文,我们将事件绑定的部分修改一下:
/**
* 在这里绑定模态框的事件
*/
initBinding() {
$('#comDelete').one('click', Company.deleteCom);
$('#confirmDelete').one('click', ()=>this.confirmDelete());
}
让我们看看编译后的 js 代码:
/**
* 在这里绑定模态框的事件
*/
Company.prototype.initBinding = function () {
var _this = this;
$('#confirmDelete').one('click', function () { return _this.confirmDelete(); });
};
这里生成了一个局部变量 _this
,是当前对象的一个相等的新的实例,通过在一个匿名的函数中调用他的 confirmDelete
方法,这样,就能够正确的解析 this
关键字为我们所希望的当前对象了
参考链接:
TypeScript里的 this