原文链接:https://note.noxussj.top/?source=helloworld
this 指向分为两种情况,一种是普通函数中使用的 this,另外一种是箭头函数中的 this。
普通函数
this 指向调用者。
场景 1
1function sayHi() { 2 console.log(this) 3} 4 5sayHi() // window
这里的 this 指向 window,因为 sayHi 的调用者是 window,可是我没有看见有 window 啊,我们要知道 window 一般都是可以省略不写的,同等于 window.sayHi()。
场景 2
1const person = { 2 sayHi: function () { 3 console.log(this) 4 } 5} 6 7person.sayHi() // person
这里的 this 指向 person,sayHi 是谁调用了? 很明显一看就知道是 person 。
场景 3
1const person = { 2 sayHi: function () { 3 console.log(this) 4 } 5} 6 7const xiaoming = person.sayHi 8 9xiaoming() // window
这里的 this 指向 window,首先是 person.sayHi 赋值给了 xiaoming,这个时候是还没调用的。那么 xiaoming 就是一个函数了,最后我们执行 window.xiaoming() ,调用者就是 window。
场景 4
1class Person { 2 constructor() {} 3 4 sayHi() { 5 console.log(this) 6 } 7} 8 9const xiaoming = new Person() 10 11xiaoming.age = 18 12 13xiaoming.sayHi()
构造函数(类)中的 this 也是一样的,sayHi 的调用者是 xiaoming,所以 this 指向它。
场景 5
1const div = document.querySelector('.content') 2 3div.onclick = function () { 4 console.log(this) 5} 6 7div.onclick() // 我们去页面点击元素,实际上就是执行的这行代码
dom 元素添加了点击事件,但是还没执行。当我们执行 div.onclick() 的时候,调用者就是 div ,所以 this 指向它。
箭头函数
这里就不用看谁是调用者了,而是看它定义时所在的环境(作用域)。箭头函数本身不存在 this,所以它的 this 指向上一层作用域所在的对象。
场景 1
1const sayHi = () => { 2 console.log(this) 3} 4 5sayHi() // window
sayHi 是一个箭头函数,本身没有 this,所以 sayHi 的 this 指向上一层作用域所在的对象,也就是 window。
场景 2
1const person = { 2 sayHi: () => { 3 console.log(this) 4 } 5} 6 7person.sayHi() // window
sayHi 的上层作用域就是全局作用域,所在的对象是 window,所以 this 指向 window。
场景 3
1const person = { 2 sayHi: function () { 3 return { 4 fn: () => { 5 console.log(this) 6 } 7 } 8 } 9} 10 11const xiaoming = person.sayHi() 12 13xiaoming.fn() // person
this 在定义时是在 fn 函数作用域中,箭头函数本身不存在 this,所以它的 this 指向上一层作用域 sayHi 所在的对象 person,所以无论是谁调用了 fn ,this 始终指向 person。
改变 this 指向
通过 call() apply() bind() 可以改变 this 指向。
apply
1const Person = { 2 name: 'xiaoming' 3} 4 5function fn(age, sex) { 6 console.log(this) // {name: 'xiaoming'} 7} 8 9fn.apply(Person, [18, '男'])
call
1const Person = { 2 name: 'xiaoming' 3} 4 5function fn(age, sex) { 6 console.log(this) // {name: 'xiaoming'} 7} 8 9fn.call(Person, 18, '男')
bind
1const Person = { 2 name: 'xiaoming' 3} 4 5function fn(age, sex) { 6 console.log(this) // {name: 'xiaoming'} 7} 8 9const ex = fn.bind(Person, 18, '男') 10 11ex()
以上三者的传参方式和执行方式不同。
apply、call 的区别:接受参数的方式不一样。
bind:不立即执行。而 apply、call 立即执行。
