理论汇总

一文搞定js this指向call、apply、bind区别问题

2021-03-25  本文已影响0人  虎牙工务员刘波

本文归类:面试造火箭,实际拧螺丝。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指向了传递的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指向问题你应该都会了,以后这座山在你心里磨平了。

上一篇下一篇

猜你喜欢

热点阅读