今天被typeScript中的this的指向弄懵了,在网上看了些资料,坐下总结:
javaScript 有一套完全不同于其它语言的对 this 的处理机制。this的指向不仅是由定义函数的方式和位置决定,同时还严重受到函数调用方式的影响
1. 在全局范围内
this 指向全局对象,浏览器是 window 对象, node 是 global 对象
TypeScript 中的this:
1 函数中的this 测试如下:
// 普通函数
function fun1(a:number)
{
this.a = a;
console.log("普通函数",this);
}
//表达式声明
var fun2 = function (a:number){
this.a = a;
console.log("表达式声明",this);
}
//lambda 函数
var fun3 = (a:number) => {
this.a = a;
console.log("Lambda函数",this)
}
fun1(14);
fun2(15);
fun3(16);
console.log("this:::",this)
编译后的js代码:
var _this = this;
// 普通函数
function fun1(a) {
this.a = a;
console.log("普通函数", this);
}
//表达式声明
var fun2 = function (a) {
this.a = a;
console.log("表达式声明", this);
};
//lambda 函数
var fun3 = function (a) {
_this.a = a;
console.log("Lambda函数", _this);
};
fun1(14);
fun2(15);
fun3(16);
console.log("this:::", this);
运行输出结果:
注意:如果tsconfig.json 中设置的是严格模式,这种函数中的this
等于undefined
,是不能这么用的,报错:
this' implicitly has type 'any' because it does not have a type annotation.ts(2683)
any
2.无嵌套类和无嵌套函数的普通类
// 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();
编译后的js代码:
// 1.无嵌套类和无嵌套函数的普通类
var Test = /** @class */ (function () {
function Test() {
var _this = this;
this.a = "outer";
this.fn2 = function () {
console.log("Test.fn2(),表达式声明:" + this.a);
};
this.fn3 = function () {
console.log("Test.fn3(),箭头函数:" + _this.a);
};
}
Test.prototype.fn1 = function () {
console.log("Test.fn1(),普通函数:" + this.a); //如果是严格模式就会报错
};
return Test;
}());
var x = new Test();
x.fn1();
x.fn2();
x.fn3();
输出的结果表明:this始终指向所在类的实例
3.嵌套类中:
// 嵌套类
class Test_q {
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); //指向的是outer
},
}
}
var xq:Test_q = new Test_q();
xq.b.fn1();
xq.b.fn2();
xq.b.fn3();
转换后的js代码:
// 嵌套类
var Test_q = /** @class */ (function () {
function Test_q() {
var _this = this;
this.a = "outer";
// 嵌套类b
this.b = {
a: "inner",
fn1: function () {
console.log("Test.b.fn1(),普通函数:" + this.a);
},
fn2: function () {
console.log("Test.b.fn2(),表达式声明:" + this.a);
},
fn3: function () {
console.log("Test.b.fn3(),箭头函数:" + _this.a); //指向的是outer
},
};
}
return Test_q;
}());
var xq = new Test_q();
xq.b.fn1();
xq.b.fn2();
xq.b.fn3();
输出的结果说明: 嵌套类里的普通函数和表达式声明函数的函数体里的this指向此嵌套类的实例,箭头函数函数里的this指向上级类的实例
4 . 嵌套函数中测试:
// 嵌套函数
class Test_qf {
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 xqf: Test_qf = new Test_qf();
xqf.fn();
编译成的js代码:
// 嵌套函数
var Test_qf = /** @class */ (function () {
function Test_qf() {
this.a = "outer";
}
Test_qf.prototype.fn = function () {
var _this = this;
var a = "inner";
function fn1() {
console.log("Test.fn()->fn1(),普通函数:" + this.a);
}
var fn2 = function () {
console.log("Test.fn()->fn2(),表达式声明:" + this.a);
};
var fn3 = function () {
console.log("Test.fn()->fn3(),箭头函数:" + _this.a);
};
function fn4() {
console.log("Test.fn()->fn4(),普通函数:" + a);
}
fn1();
fn2();
fn3();
fn4();
};
return Test_qf;
}());
var xqf = new Test_qf();
xqf.fn();
测试输出结果:嵌套的普通函数,声明表达式函数中this 指向的还是整个文件,
5 当使用 Function.prototype 上的 call 或者 apply 方法时,函数内的 this 将会被 显式设置为函数调用的第一个参数。
// call or apply 调用
function juggle() {
let result = 0;
for (let n=0; n<arguments.length; n++) {
result += arguments[n];
}
this.results = result;
}
let ninja1 = {};
let ninja2 = {};
juggle.apply(ninja1, [1,2,3,4]);
juggle.call(ninja2, 5,6,7,8);
console.log(ninja1); // { results: 10 }
console.log(ninja2); // { results: 26 }
输出结果: