接獲同事報案追查TypeScript問題,二人一起陷入迷霧近20分鐘才恍然大悟…

有段TypeScript程式自訂類別,在類別方法用this.PropName="..."修改自身屬性值(註:類似需求我習慣用self大法,寫成self.PropName="…"),偵錯時用瀏覽器F12開發者工具下指令檢查,卻發現this.PropName沒有被正確設定,我建議在程式碼加入console.log(this.PropName)交叉檢查,跑出更詭異的狀況,如下圖:

程式碼中的console.log(this.Name)得到"Jeffrey",在F12 Console下指令查this.Name卻得到undefined,WTF?

百思不得其解,許久之後才猛然想起-TypeScript的this語法糖!遇到類別方法內出現this,會偷偷將this換成_this,幫開發者節省另外宣告self、that形成Closure的麻煩。

留意上圖顯示的程式碼檔案是lab.ts而非lab.js,這是瀏覽器的德政,透過lab.js.map讓開發人員能用TypeScript原始碼偵錯,比使用編譯過的JavaScript更接近原本的演算法及程式邏輯。

開啟lab.js後真相大白。TypeScript Test()方法裡用的this,實際上已被TypeScript換成_this,永遠指向類別的Instance;而在setTimeout觸發函式的當下,從F12 Console下指令所存取的this則是DOM window,而非Player Instance,要改用_this.Name才對,TypeScript裡的this.Name有魔法加持,參考它拿來F12 Console測試,馬車變南瓜。之前幾乎都用self處理,一時不察便中招。

佛心的TypeScript為this加上魔法,貼心的瀏覽器提供TypeScript偵錯,粗心的開發者卻因此鬼打牆…

看完以上說明,一下this是Player,一下this是window,被搞得好亂,對吧?這也是我不愛TypeScript this魔法,寧可傻傻自己宣告self的理由。頭腦清楚時,還能記得this其實是_this,等那天射茶包射到天昏地暗或疲勞駕駛,難保不會再次跌坑。

評估之後,還是自己宣告self比較好。

【延伸閱讀】


Comments

Be the first to post a comment

Post a comment