JavaScript中的this到底指向谁?

很多初学JavaScript的小伙伴,都找不准函数或者方法中的this到底指向谁,其实并没有那么复杂,只需要记住一个口诀就能正确找到this的指向:不管函数或者方法是如何声明的,要看这个函数或者方法最终是谁调用的,**谁最终调用这个函数或方法,那么这个函数或方法中的this就是谁**.

下面从函数调用方式着手详细给大家介绍一下这个口诀.

1. 作为普通函数中的this

示例代码

大家都知道写一个全局函数相当于给window对象添加了一个方法,所以第5行调用welcome函数和第6行调用welcome函数本质是一样的,所以welcome函数最终是window对象在调用,所以welcome函数内部的this就指向了window对象.运行结果如下:

2. 作为对象的方法中的this

示例代码

最后1行的sayHi方法是由obj对象点出来调用的,所以sayHi方法中的this指向obj对象.所以输出的是obj对象中的name的值, 结果如下:

3. 综合案例

3.1 案例一

这里要搞明白的是第15行代码的含义, 这句话的作用是把obj对象里面的sayHi函数的函数体赋值给welcome, 所以在第16行调用welcome函数的时候,执行的代码其实是obj中sayHi的函数体. 那么执行的就是第10、11行, 那么这个this是谁呢? 其实很简单,不要看这个方法是声明在obj对象里面的, 要看这个方法是在第16行调用,是window调用的,所以此时这个this是window,输出的结果就是window的name属性,就是那个全局name的值, 结果如下:

3.2 案例二

这里同样要搞明白第15行代码的含义,这句话的意思是把welcome的函数体赋值给obj对象的sayHi函数, 所以在第16行调用obj对象的sayHi函数实际上执行的代码是第2行第3行, 那第3行的this是谁呢? 此时不要看这个welcome是怎么声明的, 要看这个代码是在第16行调用的,是obj对象点出来调用的,所以this指向obj.结果如下:

3.1 案例三

最后一行这里给人的错觉好像sayHi方法是p1点出来调用的,事实这种想法是错误的,p1点出来的只是dog对象, sayHi方法还是由dog点出来调用的,所以sayHi方法中的this还是指向dog对象.所以输出的结果如下:

4. 构造函数中的this

4.1 直接调用构造函数

大家注意看第6行,调用Student函数的时候没有用new关键字,那么这就意味着Student函数是window点出来调用的,所以Student函数中的this就是window,那么第2行第3行就是在给window添加name和age属性,值分别是黑马和12.  然后函数内部没有写return关键字那默认返回值是undefined.所以s1接受到的是undefined. 整个输出结果如下:

4.2 使用new调用构造函数

大家都知道new关键字会创建一个对象,并且会把构造函数中的this指向这个对象,并且还会把这个对象自动返回, 那么执行完第6行代码,  s1就是那个new关键字创建并返回的对象.在第2行第3行也已经给这个对象添加了name和age属性. 所以上面的代码执行结果如下:

4.3 为构造函数手动return后的情况

这里再来看看如果给构造函数添加了return关键字会如何,代码如下

说到这里大家就要注意,因为new关键字会自动帮我们返回他创建的对象,所以一般在构造函数中是不用写return返回值的, 那万一构造函数中就是写了return返回值会怎么样呢?  

这个时候就要看return关键字后面返回的值是什么类型的,如果返回的是数值类型/字符串类型/布尔类型/null/undefined,那么会忽略这个返回值. 如果返回的值不是这些类型的,比如是一个数组或者一个对象,那么这个返回值会覆盖原来new关键字自动返回的那个对象. 所以上面代码运行的结果如下:

但是构造函数中的this还是new关键字创建的那个对象(验证看第10行输出的结果), 只是这个对象返回的时候被return关键字返回的数组给覆盖了,所以s1接受不到而已.

5.  修改函数中this的默认指向

以上我们讨论的是,默认情况下,函数中this的指向。实际上JavaScript提供了一套机制,允许我们对函数中的this指向进行修改,可以让函数中的this指向我们想要让他指向的对象。

大家现在都知道上述代码中welcome函数中this指向window对象, 输出的是window, 但是我们现在想让welcome函数中的this指向obj对象,那应该怎么做呢? 

肯定是不能直接修改函数中this的指向的,直接修改会报错, 因为this被JavaScript设计为只读,代码如下:

这个时候,要实现这个效果,要想让welcome函数中的this指向obj, 就要使用函数上下文调用模式,比如call、 apply、 bind。

这个时候,welcome函数被调用,但是welcome函数内部的this就指向obj对象了。

猜你喜欢

转载自blog.csdn.net/qq_39581763/article/details/83828414