TypeScript中有三种声明函数的方法:
// 普通函数
fn1() {
console.log("XJL");
}
// 表达式声明
var fn2 = function () {
console.log("XJL");
}
// 箭头函数声明
var fn3 = () => {
console.log("XJL");
}
现在我们来演示一下,在TypeScript的类的各种情况下this作用域的范围
1.无嵌套类和无嵌套函数的普通类
class Test {
a: string = "outer";
fn1() {
console.log("Test.fn1(),普通函数:" + this.a);
}
fn2 = function() {
console.log("Test.fn2(),表达式声明:" + this.a);
}
fn3 = () => {
console.log("Test.fn3(),箭头函数:" + this.a);
}
}
var x: Test = new Test();
x.fn1();
x.fn2();
x.fn3();
输出:
Test.fn1(),普通函数:outer
Test.fn2(),表达式声明:outer
Test.fn3(),箭头函数:outer
结论:在这种情况下,this始终指向所在类的实例。
2.嵌套类
class Test {
a: string = "outer";
// 嵌套类b
b = {
a: "inner",
fn1() {
console.log("Test.b.fn1(),普通函数:" + this.a);
},
fn2: function() {
console.log("Test.b.fn2(),表达式声明:" + this.a);
},
fn3: () => {
console.log("Test.b.fn3(),箭头函数:" + this.a);
},
}
}
var x: Test = new Test();
x.b.fn1();
x.b.fn2();
x.b.fn3();
输出:
Test.b.fn1(),普通函数:inner
Test.b.fn2(),表达式声明:inner
Test.b.fn3(),箭头函数:outer
结论: 嵌套类里的属性申明时的this指向上级类的实例; 嵌套类里的普通函数和表达式声明函数的函数体里的this指向此嵌套类的实例,箭头函数函数里的this指向上级类的实例。
3.嵌套函数
class Test {
a: string = "outer";
fn() {
var a = "inner";
function fn1() {
console.log("Test.fn()->fn1(),普通函数:" + this.a);
}
var fn2 = function () {
console.log("Test.fn()->fn2(),表达式声明:" + this.a);
}
var fn3 = () => {
console.log("Test.fn()->fn3(),箭头函数:" + this.a);
}
function fn4() {
console.log("Test.fn()->fn4(),普通函数:" + a);
}
fn1();
fn2();
fn3();
fn4();
}
}
var x: Test = new Test();
x.fn();
输出:
Test.fn()->fn1(),普通函数:undefined
Test.fn()->fn2(),表达式声明:undefined
Test.fn()->fn3(),箭头函数:outer
Test.fn()->fn4(),普通函数:inner
结论:在嵌套函数体里,箭头函数的this可指向fn函数所在实例;普通函数和表达式声明函数的函数体里的this即不指向Test实例,也不指向fn(),据观察,而是指向最根部的window实例。fn4()说明了如要调用fn()里声明的变量只要直接写变量名即可。
总结:在嵌套类和嵌套函数中,具有穿透力的就是箭头函数,它总能穿过所在的类和函数,获取到上级类的属性,是什么原因造成这样的呢?我们来看一下TS转为JS后的代码
TS代码
// 含有箭头函数的类
class Test1 {
a: string = "outer";
fn = () => {
console.log(this.a);
}
}
// 不含有箭头函数的类
class Test2 {
a: string = "outer";
fn() {
console.log(this.a);
}
}
通过tsc命令转为JS代码后
// 含有箭头函数的类
var Test1 = /** @class */ (function () {
function Test1() {
var _this = this;
this.a = "outer";
this.fn = function () {
console.log(_this.a);
};
}
return Test1;
}());
// 不含有箭头函数的类
var Test2 = /** @class */ (function () {
function Test2() {
this.a = "outer";
}
Test2.prototype.fn = function () {
console.log(this.a);
};
return Test2;
}());
我们可以看到含有箭头函数的类在转为js代码后,会多一条“var _this=this;”的语句,当箭头函数要引用this时,都是调用_this,这就是穿透的秘诀~~