我有这两个Typescript类:
project.pbxproj
如何以class Base {
value: string;
lambdaExample = () => {
this.value = 'one';
}
methodExample() {
this.value = 'two';
}
}
class Child extends Base {
lambdaExample = () => {
super.lambdaExample(); // Error, because I've overwritten (instead of overridden) the method
this.value = 'three'; // ok
}
methodExample() => {
super.methodExample(); // ok
this.value = 'four'; // Error: this refers to window, not to the actual this
}
}
引用可靠,和的方式编写方法我可以覆盖方法并从父类调用它们?
答案 0 :(得分:2)
实际上很好地了解了Microsoft's Git Wiki解决这个问题的不同方法。它基本上归结为:
在实际的Wiki中有更多的规定,我真的建议你阅读整篇文章。
修改强>
包装的一个例子:
鉴于课程
class SomeClass {
public someProp: string = "Hello World";
public someMethod() {
console.log(this.someProp);
}
}
如果您从(例如)点击处理程序someMethod
调用someEl.onclick = instanceOfMyClass.someMethod;
,则会引发异常(假设window
没有属性{ {1}} 的)。
你可以通过将函数绑定到someProp
(不是类型安全,而不是ES6兼容)或通过手动包装它来实现这一点(无论如何,有效地绑定了什么):
instanceOfMyClass
它有点冗长和迂腐,但通过调用someEl.onclick = function() {
someInstanceOfMyClass.someMethod();
};
作为someMethod
的属性而不将其传递给事件处理程序(将其转换为someInstanceOfMyClass
的属性)确保window
始终是this
的实例。
答案 1 :(得分:2)
this
的范围问题可以通过一个非常简单的class装饰器解决,你不再需要使用丑陋的*箭头函数语法来解决方法 - 或者再次考虑范围问题:
function BindMethods(target: any): any {
var originalCtor = target;
var newCtor: any = function (...args) {
var c: any = function () {
// Methods are defined on prototype.
var prototype = Object.getPrototypeOf(this);
// Bind methods.
Object.keys(prototype).forEach(propertyKey => {
if (typeof this[propertyKey] === "function") {
prototype[propertyKey] = this[propertyKey].bind(this);
}
});
// Invoke original constructor.
return originalCtor.apply(this, args);
}
c.prototype = originalCtor.prototype;
return new c();
}
// Copy prototype so 'intanceof' still works.
newCtor.prototype = originalCtor.prototype;
// Overrides original constructor.
return newCtor;
}
使用它就像在类上捕捉它一样简单(methodExample
方法仅为了演示目的而被修改):
@BindMethods
class Base {
value: string;
methodExample() {
console.log(this.value);
}
}
这将确保this
的引用始终正确(即使继承):
var base = new Base();
base.value = "two";
base.methodExample(); // "two"
setTimeout(base.methodExample, 20); // "two"
不幸的是,没有办法使用方法装饰器逐个绑定方法,因为需要实例引用。如果这是一个要求,您可以使用decorator factory传递要绑定的方法的属性键。
用于方法的*丑陋。
答案 2 :(得分:1)
您对错误原因的假设是错误的,我认为这是您问题的原因......至少我理解这一点。
lambdaExample = () => {
this.value = 'one';
}
例如,此行定义了一个属性,而不是Base
上的方法,并且您无法覆盖属性。您在Base
中定义的唯一方法是methodExample
。
在Child
中,您要为lambaExample
分配一个新变量。您对super.lambaExample()
的来电失败,因为只能通过super()
访问方法;访问属性是通过this
完成的。 methodExample
课程中的Child
对我来说是一个语法错误。
请注意,您仍然可以在覆盖的Child
属性中从lambaExample
调用super,但仅限于方法。这有效:
lambdaExample = () => {
super.methodExample(); // Success on super.<somemethod>()
this.value = 'three';
}
我只知道在类中声明实例方法的一种方法,如果你与该语法一致,this
就像你期望的那样工作:
class Base {
value: string;
lambdaExample() {
this.value = 'one';
}
methodExample() {
this.value = 'two';
}
}
class Child extends Base {
lambdaExample() {
super.lambdaExample();
this.value = 'three';
}
methodExample() {
super.methodExample();
this.value = 'four';
}
}
答案 3 :(得分:1)
我找到了一个解决方法,但它很难看:
class Base {
someFunction = () => {
this.otherFunction();
}
protected otherFunction = () => {
// actual implementation here
}
}
class Child {
someFunction = () => {
this.otherFunction();
// additional implementation here
}
}
这样,您就可以在任何实例上调用someFunction
,并仍使用otherFunction
访问原始实现。