本文归类:面试造火箭,实际拧螺丝。js有三座大山,this、原型链、回调,为了帮助小伙伴们翻过大山,取得面试门槛🚪,我经过整理写了如下文章。
js this指向问题一镜到底:
为了方便理解,请用大白话理解这几个词:
this指向谁:即this是什么,console.log打印出来的this
上下文:那一行代码的上下内容,即该调用对象的内容,换句话就是对象本身
1、谁调用方法,方法内的this就指向谁的上下文
请认真看下面第一个简单的例子:
function foo(){
console.log(this)
}
foo() //window
//相当于
window.foo() //window
//相当于
window.foo.call() //window
函数调用的方法等价foo() 等价于 foo.call(context,参数1,参数2,...)
我们可以看到上面这几种写法this指向都是相同的,因为调用foo时候其实是window在调用,我们通常简写foo(),那么foo.call()写法你没见过因为你经常简写,所以没这样写过,所以你不知道。那么请你记住,从下面开始都要在你脑子里形成call调用的写法。
请记住:当call第一个参数为空时候,会默认为window
let a = 1
let obj = {
a:0,
foo:function(){
console.log(this)
}
}
//1、简写
obj.foo() // {a: 0, foo: ƒ}
//2、非简写默认下,call会传递obj做为上下文,因为obj调用了foo
obj.foo.call(obj) // {a: 0, foo: ƒ}
//3、如果参数为空,则上下文为window
obj.foo.call() //window
好了,至此你可以用这种方式理解this是什么、指向谁了。
2、this被call、apply、bind改变情况。
我们知道call、apply、bind可以改变this的指向,那么我们看到上面的第3种情况
obj.foo.call() //window
我们写call此时参数为空,this指向了window,重复那句话 当call第一个参数为空时候,会默认为window
,所以此时这种情况正常。好,现在我们试着给他传递一个任意参数:
let a = 1
let obj = {
a:0,
foo:function(){
console.log(this) //6666
}
}
obj.foo.call(6666)
`//this指向了我们随便写的参数6666,打印结果得到666666
我们发现此时this指向了传递的6666,所以此时this指向被我们所写的call改变了,这就是this指向被绑定改变的说法了。
call、apply两着类似,区别只是后面传参格式不一样:
apply参数为apply(context,[参数1,参数2,参数3...])
call参数为call(context,参数1,参数2,参数3...)
好,到这里如果没多大问题的话,你已经知道了call、apply的运用以及区别,接下来我们看下bind。
let a = 1
let obj = {
a:0,
foo:function(aa,bb){
console.log(this)
console.log('bb',bb)
}
}
obj.foo.bind(obj,1,2,3,4) //传参与call相同
没错这就是bind与call、apply两者的区别,它不会直接运行这个函数,而是返回该this被改变的函数,所以请记住:下次你运行这个函数时候,里面的this就是你bind过的this。
至此call、apply、bind这几个你就都会了。
3、箭头函数this指向
箭头函数比较特殊,但也没什么好说的,我们可以发现,上面的普通函数this不是固定的,取决于谁调用它,它才指向谁。那么请反过来记住:箭头函数this是固定的,它在被定义时候就已经被决定了this的指向。就是说写了一个箭头函数,那么你的this就相当于已经同时被定义死了,指向当前环境父级的上下文。call、bind、apply无法改变箭头函数的this指向。
至此this指向问题你应该都会了,以后这座山在你心里磨平了。