介绍
在 JavaScript(和 TypeScript)中,this 关键字的行为与其他语言中非常不同。 这可能会令人惊讶typescript 全局定义类型,特别是对于其他语言的用户来说,他们依靠直觉来想象这个关键字的行为。
本文将教你如何在 TypeScript 中识别和调试这个问题,并提供一些解决方案及其各自的优缺点。
典型症状和危险因素
失去这种背景的典型症状包括:
程序中应出现以下代码:
JavaScript 中的 this 到底是什么?
有很多文章介绍了 JavaScript 中 this 关键字的危险。 在这里或这里查看。
当调用 JavaScript 中的函数时typescript 全局定义类型,可以按照以下顺序推断出 this 指向的内容(这些规则按优先级顺序排列):
这些规则产生了违反直觉的疗效。 例如:
class Foo {
x = 3;
print() {
console.log('x is ' + this.x);
}
}
var f = new Foo();
f.print(); // Prints 'x is 3' as expected
// Use the class method in an object literal
var z = { x: 10, p: f.print };
z.p(); // Prints 'x is 10'
var p = z.p;
p(); // Prints 'x is undefined'
对此的危险信号
您应该注意的最大危险信号是当您要使用类方法时不要立即调用它。 任何时候您看到一个类方法被引用但没有使用相同的表达式来调用它,这可能是错误的。
例子:
var x = new MyObject();
x.printThing(); // SAFE, method is invoked where it is referenced
var y = x.printThing; // DANGER, invoking 'y()' may not have correct 'this'
window.addEventListener('click', x.printThing, 10); // DANGER, method is not invoked where it is referenced
window.addEventListener('click', () => x.printThing(), 10); // SAFE, method is invoked in the same expression
维修
有一些方法可以维持这个上下文。
使用实例函数
您可以使用实例箭头函数来定义类成员,而不是 TypeScript 中的默认原型方法:
class MyClass {
private status = "blah";
public run = () => { // <-- note syntax here
alert(this.status);
}
}
var x = new MyClass();
$(document).ready(x.run); // SAFE, 'run' will always have correct 'this'
局部脂肪箭头
在TypeScript中(这里添加一些参数以供解释):
var x = new SomeClass();
someCallback((n, m) => x.doSomething(n, m));
函数.bind
var x = new SomeClass();
// SAFE: Functions created from function.bind are always preserve 'this'
window.setTimeout(x.someMethod.bind(x), 100);
发表评论