JavaScript中apply, call和bind的区别

首先要知道,JavaScript中apply,call 和 bind的作用基本都是一样的,就是用来改变函数执行时的上下文,或者说改变函数的this对象指向

在详细了解它们的区别之前,我们先来看一个例子

var name = "mike";
const obj = {    
              name: "luke",
              say:function()
             {
                   console.log(this.name);
             }
         };
obj.say();  //输出luke

setTimeout(obj.say,0) // 输出mike

 这里,会不会觉得很奇怪,第一个obj.say()输出luke应该很好理解,因为这个时候this指向的就是obj对象,所以this.name, 肯定就是obj里面的name => luke

第二个setTimeout(obj.say,0) 为什么输出的mike呢,这里会感觉很奇怪 => setTimeout()这是个定时器,里面的第一个参数是个回调函数,也就是说obj.say是作为回调函数来执行的, 执行回调函数,需要回到主栈上执行,也就是在全局执行上下文的环境中执行,这个时候的this指向的是windows, 所以,这个时候调用obj.say => 输出 this.name => this指的是全局的windows对象,所以返回的是mike

那么问题来了,现在我的需求就是,在定时器中调用回调函数obj.say,但是我要的是输出luke,而不是mike, 我应该怎么办,有没有方法呢    => 首先我们想,我们要达到的目的,就是在setTimeout(obj.say,0)中,改变这里面的obj.say方法里面的this的指向,现在它指向的是windows全局对象,我们要把它指向obj, 那有没有方法做到这点呢 =》 这就是我们今天要讲的这3个东西,改变函数的this对象指向 或者说 改变函数执行时的上下文

先说结果 =》 这里可以这么改     setTimeout(obj.say.bind(obj),0); 通过使用.bind(obj) 来把this绑定obj对象,此时,输出的就是luke 

call,apply,bind都是Function.prototype下的方法,目标都是改变函数的上下文, 最终的返回值是你调用方法的返回值, 如果该方法没有返回值, 那么就是返回undefined

call 和 apply基本是一样的,作用也完全一样,唯一不同就是接受参数的方式不一样(apply的第二个参数是一个数组或者arguments对象, callc从第二个参数开始,后面是参数列表). 你可以把call看做是apply的语法糖。 call 和 apply一样,都是立即执行调用.

这点和bind不一样,bind是返回绑定this之后的函数,一个新函数

语法:

apply([thisObj[,argArray]])

call([thisObj[,arg1[, arg2[, [,.argN]]]]])  

上面 thisObj的取值有以下4种情况:

1. 不传, 或者null, undefined, 函数中的this指向window对象

2.  传递另一个函数的函数名, 函数中的this指向这个函数的引用

3.  传递字符串,数值或布尔类型等基础类型, 函数中的this指向其对应的包装对象 String, Number, Boolean

4.  传递一个对象,函数中的this指向这个对象

 

总结:

apply,call 和 bind都可以改变函数的this指向,都是可以用来改变函数执行时的上下文

它们的第一个参数都是this要指向的对象,如果没有这个参数,或者参数为undefined,或者为null, 则默认指向全局的window

三者都可以传参,但是apply是数组, call是参数列表,而且apply和call是一次性传入参数, 而bind可以分多次传入

bind是返回绑定this之后的函数,一个新函数. 而apply, call则是立即执行调用

 

三者的使用场景:

如果不需要关心具体有多少参数被传入函数,选用apply()

如果确定函数可接收多少个参数,并且想一目了然地表达形参和实参的对应关系,用call()

如果我们想返回一个新函数以供后面调用,不需要立即得到函数返回结果,使用bind()

 

posted on 2023-09-12 11:40  新西兰程序员  阅读(7)  评论(0编辑  收藏  举报