我有两个TypeScript类;其中一个有一个方法,它返回对第二个类的实例中的不同方法的引用(是的,有点令人困惑)。这是仍然重新解决问题的最简单的例子(我为那些更喜欢在底部的人包括了编译的JS):
class OuterClass {
public InnerClassInstance: InnerClass;
constructor() {
this.InnerClassInstance = new InnerClass(7); //Create an instance of the inner class
//7 is just a test value
}
public DoStuff(): any { //Return a reference to the instance's method
return this.InnerClassInstance.DoMoreStuff;
}
}
class InnerClass {
public VariableInstance: number; //Keep a variable (this is the main issue)
constructor(Num: number) {
this.VariableInstance = Num;
}
public DoMoreStuff() {
alert(this.VariableInstance); //Demonstrate (hopefully) that everything worked
//Displays 'undefined' instead
}
}
var OuterClassInstance: OuterClass = new OuterClass();
OuterClassInstance.DoStuff()(); //Call DoMoreStuff from the instance in OuterClass
问题是,一旦DoMoreStuff
被调用,它似乎已经失去了与它的父类的所有连接。此时,实例InnerClassInstance
仍然正确(变量为7),但直接从VariableInstance
访问时DoMoreStuff
未定义。所有在InnerClass
内定义的变量都会发生这种情况。
我错过了某种规格吗?我认为引用会保留它的上下文,但是当从引用中调用它时,它似乎会失去它。
这是JS:
var OuterClass = (function () {
function OuterClass() {
this.InnerClassInstance = new InnerClass(7); //Create an instance of the inner class
//7 is just a test value
}
OuterClass.prototype.DoStuff = function () {
return this.InnerClassInstance.DoMoreStuff;
};
return OuterClass;
})();
var InnerClass = (function () {
function InnerClass(Num) {
this.VariableInstance = Num;
}
InnerClass.prototype.DoMoreStuff = function () {
alert(this.VariableInstance); //Demonstrate (hopefully) that everything worked
//Displays 'undefined' instead
};
return InnerClass;
})();
var OuterClassInstance = new OuterClass();
OuterClassInstance.DoStuff()(); //Call DoMoreStuff from the instance in OuterClass
答案 0 :(得分:2)
DoMoreStuff
(即不作为方法调用),因此this
获取window
全局对象的值。
DoMoreStuff
正试图获取window.VariableInstance
,这确实是未定义的。
您需要做的工作如下:
var InnerClass = (function () {
var _this = this; // <--- closure for class instance
function InnerClass(Num) {
this.VariableInstance = Num;
}
InnerClass.prototype.DoMoreStuff = function () {
alert(_this.VariableInstance); // <--- using class instance
};
return InnerClass;
}
在阅读其他响应后,看起来bind()就是解决方案。麻烦的是,它只受ECMA5浏览器支持,因此旧的IE版本不会有它。
bind()的可能替代是:
function bind (proc, _this) {
if (proc.prototype.bind) return proc.bind (_this);
return function () { proc.call (_this); };
}
答案 1 :(得分:2)
如果要传递函数,可以使用arrow functions
:
public DoMoreStuff = () => { // you plan to pass this function around
alert(this.VariableInstance); //Demonstrate (hopefully) that everything worked
//Displays 'undefined' instead
}
完整的代码:
class OuterClass {
public InnerClassInstance: InnerClass;
constructor() {
this.InnerClassInstance = new InnerClass(7); //Create an instance of the inner class
//7 is just a test value
}
public DoStuff(): any { //Return a reference to the instance's method
return this.InnerClassInstance.DoMoreStuff;
}
}
class InnerClass {
public VariableInstance: number; //Keep a variable (this is the main issue)
constructor(Num: number) {
this.VariableInstance = Num;
}
public DoMoreStuff = () => { // you plan to pass this function around
alert(this.VariableInstance); //Demonstrate (hopefully) that everything worked
//Displays 'undefined' instead
}
}
var OuterClassInstance: OuterClass = new OuterClass();
OuterClassInstance.DoStuff()(); //Call DoMoreStuff from the instance in OuterClass
它不是默认值的原因是它消耗更多内存(因为箭头成员继续this
而不是prototype
)并且它不是继承友好的(同样{{1 }}与this
逻辑)。
答案 2 :(得分:1)
this
对象的值由正在使用的方法调用模式确定。当函数作为函数(OuterClassInstance.DoStuff()();
)而不是作为方法(object.method()
)调用时,它将绑定到Global
对象。
OuterClass.prototype.DoStuff = function () {
return this.InnerClassInstance.DoMoreStuff;
};
OuterClassInstance.DoStuff()()
与:
var doStuff = OuterClassInstance.DoStuff();
doStuff();
由于Global对象上没有名为VariableInstance
的属性,因此会生成undefined
。
要解决此问题,请使用InnerClass
Function.prototype.bind
实例的函数
OuterClass.prototype.DoStuff = function () {
return this.InnerClassInstance.DoMoreStuff.bind(this.InnerClassInstance);
};
考虑这个例子:
var o = {
a: 'asdf',
method: function () {
return this.other;
},
other: function () {
alert(this.a);
}
};
o.method()(); //alerts undefined
method: function () {
return this.other.bind(this);
}
o.method()(); //alerts asdf