白鹭三剑客TypeScript 中的 this指向问题

Posted 白鹭引擎

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了白鹭三剑客TypeScript 中的 this指向问题相关的知识,希望对你有一定的参考价值。

Egret

三剑客

“白鹭三剑客”是白鹭技术顾问解析白鹭产品,分享行业经验,预测行业趋势的版块,白鹭在此保证:无干货不分享!


今天(9月10日)是中国的教师节,作为白鹭引擎的布道师,一直以来肩负着传道授业的责任,在这里“白鹭三剑客”祝全国的教师们节日快乐!同时,今天“白鹭三剑客”的张鑫磊将为各位带来《TypeScript 中的 this指向问题》。



张鑫磊:白鹭引擎布道师,微软MVP,知名博客主。曾就职于搜狐畅游担任技术主管,拥有多年游戏开发经验,曾担任Flash资深培训讲师。开源硬件爱好者,热衷于新鲜技术分享,拥有独立IP访问超过800万的个人博客ashan.org。


如果你接触过TypeScript有一段时间,那么你会发现很多并非语言设计当中的“特征”。这些所谓的特征并非真正TypeScript的语法糖部分,也并非语言设计当中绝妙的点子。仔细研究TypeScript代码与编译后的 javascript 代码,你会发现,很多东西其实都是委曲求全的产物。


这篇文章里,我们仅来讨论关于TypeScript中 this 作用域的问题,你应该透过我的描述来了解如何去理解问题的思路。

我们来一段 TypeScript 代码:


执行 tsc 编译器,在同目录中生成一个a.js文件,内容如下:
【白鹭三剑客】TypeScript 中的 this指向问题
生成的JS代码并不难理解,还是先回过头来看 TypeScript 代码。

当我们创建一个类,并在类中定义了一个私有属性,在 TypeScript 中的解释为,名称为 str 的属性作用域在类中。 str 与 方法 abc 所在同一域中,并且属于平行关系。记住,这种解释是在 TypeScript 中存在的。

我们简单修改一下生成后的 JavaScript 代码,新代码内容如下:
【白鹭三剑客】TypeScript 中的 this指向问题
最后两行是我手动添加的,在nodejs中运行,可以看到打印出 “hello” 字符。
【白鹭三剑客】TypeScript 中的 this指向问题

现在已经确保我们的代码没有任何问题,可以正常执行。

在 TypeScript 中,我们看到 abc 方法在访问 str 属性时候添加了 this. 。在其他编程语言中,通常函数内的调用都会先从函数域开始检索,然后寻找上一层域中的定义。

但如果你在 TypeScript 中这么做了,就无法找到上一层的 str 定义。在编译过程中,你将得到一个报错信息。

TypeScript 这么做的目的是为了防止域指向错误,在得到的翻译后的JS代码中,依然保留相同语句,已防止错误的发生。

在来看另外一种情况,回调函数。看一下修改后的JS代码:
【白鹭三剑客】TypeScript 中的 this指向问题
运行后得到什么结果?

会先输出一个 hello 在输出一个 undefined 。恭喜你,你已经遇到了JS当中最恶心人的作用域问题了。

在JS中,如何避免这种问题呢?一般是将 this 赋值给另外一个变量,通过这种方式来避免作用域问题。

修改代码如下:
【白鹭三剑客】TypeScript 中的 this指向问题
此时你能看到输出两个 hello 字符。到此为止你已经找到了解决方法,但是,你仍然无法通过一些巧妙的手段让 TypeScript 翻译成现在的样子。

但TypeScript提供了一个另外一个变通的解决方法,来实现这个功能。
【白鹭三剑客】TypeScript 中的 this指向问题
这样的TS代码翻译之后得到如下JS代码:
【白鹭三剑客】TypeScript 中的 this指向问题
在JS中增加两行代码:
【白鹭三剑客】TypeScript 中的 this指向问题
你会看到打印出了 undefined ,我们需要稍微修改一下 TypeScript 代码。
【白鹭三剑客】TypeScript 中的 this指向问题
可以看到一个非常不规范的语法,语法格式为 ()=>{}。 翻译之后的JS代码如下:
不难看出 TypeScript 是将这种技巧封装到了语言层面,并为其取名叫做 “Arrow Function”。


传送门:点击下面文章查看“白鹭三剑客”张鑫磊的更多技术干货

近期活动
【白鹭html5移动开发者沙龙】9月19杭州站报名正式开启

时间:
2015年9月19日 14:00-17:30
地点:
泰豪迭代创空间
江干区九环路9号国家大学科技园D座10楼

联系我们
开发者技术交流区:bbs.egret.com
合作开放平台:open.egret.com
商务合作:bd@egret.com
招聘邮箱:hr@egret.com
产品合作QQ:249446251
 渠道合作QQ:2506665915

以上是关于白鹭三剑客TypeScript 中的 this指向问题的主要内容,如果未能解决你的问题,请参考以下文章

白鹭直播间:聊聊Egret引擎4.0 与 TypeScript 2.1~

typescript 属性默认值使用箭头函数 this指向问题

什么是白鹭引擎

Typescript核心篇——函数_this指向—重载—泛型

白鹭引擎开发H5游戏(项目结构)

egret白鹭引擎入门(第一章)