call、apply和bind的区别及this的指向

this 关键字

在介绍call()、bind()和apply()之前先了解一下this 关键字
根据MDN的介绍

当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。
this 不能在执行期间被赋值,并且在每次函数被调用时 this 的值也可能会不同。
在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)。

由此可知this的值不能被设置,并且this的值是会变化的的,是由函数的调用方式决定的。
this的值有以下几种情况

  1. 在全局作用域下,this一般指向全局对象
console.log(this === window);

在这里插入图片描述
此时this指向的是全局对象window
2. 在函数中this的值取决于函数的调用方式

funtion test(){
     
	return this;
}
console.log(test());

在这里插入图片描述
在全局作用域调用函数,此时,this指向全局对象window

var test = {
     
	color:'red',
	getColor:function(){
     
	return this.color;
	}
}
console.log(test.getCOlor());

在这里插入图片描述
此时输出的是red也就是test对象中的color属性的值。
当函数作为对象中的一个属性时,函数的中的this指向调用该函数的对象。
由以上示例我们可以明白this的值由函数的调用方式决定的意思。

改变 this 的指向

既然this无法被设置那么我们如何更改this的指向呢,js提供了call()、apply()、bind()三个方法可以改变this的指向。
那么如何使用呢

call()

该方法是由函数来调用的
该方法的第一个参数是期望this指向的值,通过这个参数可以让this的指向发生改变
后面的参数是要调用的函数的参数

function test(a,b){
     
	return a+b+this.c+this.d;
}
var obj = {
     
	c:23,
	d:43
}
var result = test.call(obj,5,6);//此时调用test()方法的将是obj,this的将指向obj这个对象
console.log(result);

在这里插入图片描述
由此可见,计算的结果是obj对象中的两个属性的值和传入的参数的值相加的结果,就是说this指向了obj对象,this的指向被改变了

apply()

该函数该方法的第一个参数是期望this指向的值,通过这个参数可以让this的指向发生改变
第二个参数是一个数组,数组中的值应当是要调用的函数的参数

function test(a,b){
     
	return a+b+this.c+this.d;
}
var obj = {
     
	c:23,
	d:43
}
var result = test.apply(obj,[5,6]);//此时调用test()方法的将是obj,this的将指向obj这个对象
console.log(result);

借用上面的代码结果还是77,此时要注意的是apply()方法的参数的形式与上面的不同

bind()

该函数该方法的第一个参数是期望this指向的值,通过这个参数可以让this的指向发生改变
后面的参数是要调用的函数的参数
```javscript
function test(a,b){
     
	return a+b+this.c+this.d;
}
var obj = {
     
	c:23,
	d:43
}
var result = test.bind(obj,5,6);//此时调用test()方法的将是obj,this的将指向obj这个对象,5和6 是test函数的参数
console.log(result);

在这里插入图片描述
此时输出的结果不再是预想中的77了而是一个函数体,为什么呢。
result 是函数通过bind()调用的返回值,也就是说函数调用bind()函数会返回一个函数,这是值得注意的
那么既然返回一个函数体那么就能调用

//调用上面的代码的result
console.log(result());

在这里插入图片描述
此时的结果和我们的预想一样,由此我们可以知道bind()不仅能改变this的指向还返回一个函数。

call()、apply()、bind()的区别

他们之间的区别在刚才演示的过程中可以略窥一二,下面进行总结

  1. 参数方面的不同
    call()、apply()、bind()的第一个参数都是一样的都是想让this指向的值,主要的区别在后面的参数
    call()和bind()的第一个参数后面的参数是一个列表形式,就是正常传参
    apply()的第一个参数后面的参数是一个数组,数组的中的元素就是要调用的函数的参数
  2. 返回值方面的不同
    通过刚才的演示我们可以得知call()和apply()都是调用函数后将被调用的函数的返回值返回
    bind()则是返回一个函数,所以可以利用bind()将它的返回值多次调用
  3. 执行方面的不同
    call()、apply()都是直接执行调用他们的函数
    bind()只是返回一个函数并不执行该函数,需要再手动执行一下
    根据上面的区别我们可以根据自己的需求进行选择
    比如如果想让函数立即执行就选择call()或apply()
    如果想要多次调用函数就选择bind()
    如果不想用数组的形式传参又想让函数立即行就选择call()

总结

  1. this的值是多变的,由函数的调用方式决定this的值,函数的调用方式有比较多所以导致this的值多变
  2. 即便this的值多变让程序员很难确定,也可以通过call()、apply()、bind()手动更改this的指向
  3. bind()的返回值是一个函数,并且不会立即执行

你可能感兴趣的:(JavaScript学习记录,javascript)