js中apply,call,bind的区别与用法

2 篇文章 0 订阅
1 篇文章 0 订阅

在JavaScript中,所有的函数再被调用的时候都会默认传入两个参数,一个是this,还有一个是arguments。在默认情况下this都是指当前的调用函数的对象。但是有时候我们需要改变this的指向,也就是说使函数可以被其他对象来调用,那么我们应该怎样做呢?这时候我们就可以使用call,apply和bind方法了。
this指向 = 谁调用,指向谁(这是错误的!!!)
this永远指向最后一个调用它的那个对象(正解)
如何解决this指向问题?
1.使用ES6中箭头函数
2.函数内部使用_this = this
3.使用apply,call,bind方法
4.new实例化一个对象

一:call,apply和bind方法的来历

在js中所有的函数都是Function的实例,而且对于Function来说,它的原型即Function.prototype中含有很多东西,其中call,apply和bind方法就是Function原型中的方法,所以根据原型的规则,所有的函数都可以使用原型中属性和方法,所以来说,对于所有的函数都可以使用call,apply和bind方法。
简单一句话:call,apply和bind都是Function原型中的方法,而所有的函数都是Function的实例。

我认为它们的作用可以用一句话来描述:就是改变this的指向。对于这句话的解释,我们可以结合代码来理解。

二:call函数

首先我们放个截图看看官方对call的解释:

从图示上我们可以看到,方法解释为:调用对象的方法,将另一个对象替换为当前对象。

两个参数,thisArg:要用作当前对象的对象。argArray:传递给方法的参数列表。

怎么理解呢,下面放个代码图方便直观解释下:

在上面的截图中我们可以明确的看到,在调用test()方法后传入参数后,this的指向为全局对象。

为方便区分,我们再用call函数改变this的指向。

在这张图上,我们在调用test方法时,使用call函数,在call函数里传递了person对象及属性birthday,我们可以看到再次打印出来的this已经变成了person对象。

综上,可以得出结论:call函数传递两个参数(一个用来改变this指向的对象(必传),一个用于使用的参数列表(选传))。

三:apply函数

接下来我们看看apply函数。
apply() 方法调用一个函数,其具有一个指定的this值,以及作为一个数组(或者类似数组的对象)提供的参数。

官方对apply的解释是:对于给定的函数,创建一个与原始函数具有相同主体的绑定函数。绑定函数的this对象与指定对象相关联,并具有指定的初始参数。

两个参数:

thisArg:在fun函数运行时指定的this值。指定this的值并不一定是函数执行时真正的this值,如果是原始值的this会指向该原始值的自动包装对象。

argArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给fun函数。参数为null或者undefined,则表示不需要传入任何参数。

我们可以看到,在apply中传入person对象和参数数组(这里我们直接使用Object.values()将person对象的属性值直接转化为数组了)。打印出来的this指定依旧被改变为person对象了。

四:bind函数

最后我们看看bind函数。
bind() 方法对于给定的函数,创建一个与原始函数具有相同主体的绑定函数。绑定函数的this对象与指定对象相关联,并具有指定的初始参数。

thisArg:this关键字可以在新函数中引用的对象。

argArray:传递给新函数的参数列表。

可以看到,bind创建了一个源函数相同的函数,且拥有this对象及参数列表。

call,apply,bind都是js里改变this指向的函数,不同的是,call只接受一个参数,apply接收一个数组,bind创建一个同源函数。

五:call的应用

比如判断数据类型:


console.log(Object.prototype.toString.call("qq"))            // [Object String] 返回值都是字符串类型
console.log(Object.prototype.toString.call(12))              // [object Number]
console.log(Object.prototype.toString.call(false))           // [object Boolean]
console.log(Object.prototype.toString.call(undefined))       // [object Undefined]
console.log(Object.prototype.toString.call(null))            // [object Null]
console.log(Object.prototype.toString.call(function(){}))    // [object Function]
console.log(Object.prototype.toString.call([]))              // [object Array]
console.log(Object.prototype.toString.call({}))              // [object Object]

然后进行封装

很简单的实现了类型判断。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值