this ts 方法获取_TypeScript 中的 this指向问题

本文探讨了TypeScript中this的作用域问题,通过示例展示了在类方法、回调函数中可能出现的指向错误。文章提到了在JavaScript中常见的解决方案,如保存this到另一个变量,以及TypeScript提供的箭头函数来保持正确的上下文。同时,介绍了如何通过使用箭头函数在TypeScript中避免作用域问题。
摘要由CSDN通过智能技术生成

TypeScript 中的 this指向问题

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

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

我们来一段 TypeScript 代码:

class demo

{

private str:string = "hello";

public abc()

{

console.log( this.str );

}

}

执行 tsc 编译器,在同目录中生成一个a.js文件,内容如下:

var demo = (function () {

function demo() {

this.str = "hello";

}

demo.prototype.abc = function () {

console.log(this.str);

};

return demo;

})();

生成的JS代码并不难理解,还是先回过头来看 TypeScript 代码。

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

我们简单修改一下生成后的 JavaScript 代码,新代码内容如下:

var demo = (function () {

function demo() {

this.str = "hello";

}

demo.prototype.abc = function () {

console.log(this.str);

};

return demo;

})();

var d = new demo();

d.abc();

最后两行是我手动添加的,在nodejs中运行,可以看到打印出 “hello” 字符。

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

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

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

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

在来看另外一种情况,回调函数。看一下修改后的JS代码:

var demo = (function () {

function demo() {

this.str = "hello";

}

demo.prototype.abc = function () {

console.log( this.str);

};

demo.prototype.doing = function(callback){

callback();

}

return demo;

})();

var d = new demo();

d.abc();

d.doing(d.abc);

运行后得到什么结果?

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

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

修改代码如下:

var demo = (function () {

var that;

function demo() {

this.str = "hello";

that = this;

}

demo.prototype.abc = function () {

console.log( that.str);

};

demo.prototype.doing = function(callback){

callback();

}

return demo;

})();

var d = new demo();

d.abc();

d.doing(d.abc);

此时你能看到输出两个 hello 字符。到此为止你已经找到了解决方法,但是,你仍然无法通过一些巧妙的手段让 TypeScript 翻译成现在的样子。

但TypeScript提供了一个另外一个变通的解决方法,来实现这个功能。

class demo

{

private str:string = "hello";

public abc()

{

console.log( this.str );

}

public doing(callback)

{

callback();

}

public start()

{

this.doing(this.abc);

}

}

这样的TS代码翻译之后得到如下JS代码:

var demo = (function () {

function demo() {

this.str = "hello";

}

demo.prototype.abc = function () {

console.log(this.str);

};

demo.prototype.doing = function (callback) {

callback();

};

demo.prototype.start = function () {

this.doing(this.abc);

};

return demo;

})();

在JS中增加两行代码:

var d = new demo();

d.start();

你会看到打印出了 undefined ,我们需要稍微修改一下 TypeScript 代码。

class demo

{

private str:string = "hello";

public abc()

{

console.log( this.str );

}

public doing(callback)

{

callback();

}

public start()

{

this.doing(()=>{this.abc()});

}

}

可以看到一个非常不规范的语法,语法格式为 ()=>{}。 翻译之后的JS代码如下:

var demo = (function () {

function demo() {

this.str = "hello";

}

demo.prototype.abc = function () {

console.log(this.str);

};

demo.prototype.doing = function (callback) {

callback();

};

demo.prototype.start = function () {

var _this = this;

this.doing(function () { _this.abc(); });

};

return demo;

})();

不难看出 TypeScript 是将这种技巧封装到了语言层面,并为其取名叫做 “Arrow Function”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值