这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战
this指向
01. this
(1)一般情况下
-
this永远指向最后调用它的那个对象,谁调用就指向谁(万能口诀) -
匿名函数的
this永远指向window -
回调函数内的
this指向的是window- 当将一个函数作为参数传递时,会丢失
this的绑定
- 当将一个函数作为参数传递时,会丢失
-
开启严格模式后:
"use strict"- 开启后,函数内的
this将指向undefined - 但全局下的
this还是指向window
- 开启后,函数内的
-
定义变量的方式不同:
var、let、const- 全局下定义的变量,只有
var定义的变量才会绑定到window上 let、const定义的变量都不会绑定在window上
var name = 'window' window.name = 'window'
- 全局下定义的变量,只有
(2)构造函数
-
构造函数内的
this,指向其通过new操作符,创建的实例对象- 注意,箭头函数是无法做构造函数的
let cat = new Animal() // 构造函数内的 this 指向其创建的实例,且不会被任何方式修改
(3)箭头函数
-
箭头函数没有
this,它内部的this取决于它外面的第一个不是箭头函数的函数的this- 箭头函数指向外层函数创建时的
this,而非执行时 - 箭头函数会通过作用域链来查找其
this
- 箭头函数指向外层函数创建时的
-
字面量创建的对象不是作用域,其作用域是
window,所以对象内部的箭头函数的this指向window- 注意,作用域只包括全局作用域和局部函数作用域
-
构造函数创建的对象,作用域是可以理解为是这个构造函数,且这个构造函数的
this是指向新建的对象的,因此this指向这个实例对象 -
箭头函数中
this一旦绑定了上下文,就不会被任何代码改变- 无法通过
call、apply、bind改变 - 但可以通过改变作用域下的
this来间接修改
function father(){ return () => { return () => { console.log(this) // 这里的 this 是father函数的 this } } } let obj = { name: 'ruovan', foo1: () => { // 这里的this指向其外层作用域的this => window // obj不属于局部作用域,它是一个对象 console.log(this.name) }, foo2: function() { console.log(this.name) // return () => { // 这里的 this 在函数 foo2 作用域下 // 所以这里的 this 指向这个 obj 对象 console.log(this.name) } } }
- 无法通过
(4)改变指向
-
可以通过 call、apply、bind 改变this指向
- 使用
.call()或者.apply()的函数是会直接执行的 - 使用
.bind()是创建一个新的函数,需要手动调用才会执行-
且,通过
bind函数中改变this后,其不会再被call、apply修改
-
- 使用
-
如果
call、apply、bind接收到的第一个参数是空或者null、undefined的话,则会忽略这个参数- 即相当于没有使用
-
forEach、map、filter函数的第二个参数也是可以显式绑定this并改变指向的// 通过 call、apply、bind 改变this指向 func() // this == else func.call(else, arg1, arg2, ...) func.apply(else, [arg1, arg2, ...]) func.bind(else) // bind 的this 不会被修改 func.bind(else).call(other) // this == else
(5)图解this
-图来源: 点击这里查看,侵删
下一篇文章会简单介绍手写 call | apply | bind 方法
本人前端小菜鸡,如有不对请谅解