問題
TypeScript在配置表需要直接配置某個類的指定方法。比如[“ClassA”,“Show”]代表ClassA.Show()。
代碼如下
class ClassA {
private m_value: number = 0;
private static s_name: string = "";
public static Show() {
this.s_name = "l2xin";
console.log("ClassA.Show():", this)
ClassA.Init();
}
public static ShowFunc = function () {
this.s_name = "l2xin";
console.log("ClassA.ShowFunc():", this)
ClassA.Init();
}
private SetValue() {
this.m_value = 2;
}
private static Init() {
}
}
測試代碼
function Test() {
let a: ClassA = new ClassA();
let myClass = window["ClassA"];
//ShowFunc中this爲ClassA
myClass.Show();
//ShowFunc中this爲ClassA
myClass.ShowFunc();
/**使用字符串獲得方法 */
let func: Function = myClass["Show"];
//func執行時this爲window
func();
//執行時this爲ClassA 正常
func.call(myClass);
}
測試結果
-
myClass.Show();
-
myClass.ShowFunc();
-
let func: Function = myClass["Show"]; func.call(myClass);
ClassA.Show(): ƒ ClassA() { this.m_value = 0; }
-
let func: Function = myClass["Show"]; func();
ClassA.Show(): Window
前三種執行的結果都和預期相符,函數中的this都是ClassA。
最後一種func()中this代表的是Window。
分析
Ts和Js在一個方法中(如果是ts,這裏僅限於非lambda表達式定義的方法)有使用this關鍵字,那麼可以按照下面的優先級順序來推斷this指向的是什麼:
- 如果這個函數是function#bind調用的結果,那麼this指向的是傳入bind的參數
- 如果函數是以foo.func()形式調用的,那麼this值爲foo
- 直接func(),如果是在嚴格模式下,this將爲undefined,否則,this將是全局對象(瀏覽器環境裏爲window)
詳細文檔看這裏:
Understanding JavaScript Function Invocation and “this”
綜上,我理解Ts的this是這樣:
- 調用x.func();則 func()中this就是x,
- 如果是匿名函數或者把函數類型變量,即let myFunc = x.func; myfunc中的this則根據上下文來決定,全局就爲window。
對比lua的self.func() self:func()還有python的面向對象理解起來更有意思。
其他
下面這兩種實現都可以滿足需求
-
public static ShowFunc = function () {}
-
public static Show() {}
個人推薦使用第二種,Class內部實現會比較自然。
let func: Function = myClass["Show"];
func.call(myClass);