当前位置:网站首页>如何实现call、apply、bind
如何实现call、apply、bind
2022-08-08 22:43:00 【MonsterQy】
前言
该文章不再说明他们的具体用法,直接说明他们的内部实现原理
一、call的实现
思考一个问题:我们在执行call方法时总是是对某函数调用该方法,既然想让每个函数都有该方法,所以call这个方法应该写到它的原型上,即Function.prototype.call=function(){},那我们又知道call的作用是改变this指向,这个原理是怎么样的呢 我们先进行如下尝试,看看this究竟是什么
function person()
{
console.log(this.name)
}
var egg={
name:'123'}
Function.prototype.mycall=function(obj)
{
console.log(this)
}
person.mycall(egg)
可以看到我们若不对this指向进行修改,则它依旧指向的是函数本身(this指向这个函数意思也就是它和这个函数值相同!!!),而我们的目的是将this指向obj这个参数,那么怎么改this呢?我们知道this总是指向最后调用它的对象,所以我们要通过obj去调用一下person方法,就可以成功让this指向obj然后再删除这个调用。也就完成了this的显示绑定。
1.初实现:
(记住this总是指向最后调用它的那个对象!!!)
Function.prototype.myCall=function(obj)
{
console.log(this) //谁调用myCall谁就是this
obj.fn=this //令这个obj的一个属性=this
obj.fn()//通过调用(执行)绑定this到obj上
delete obj.fn //它的使命完成了 删除即可
}
2.进一步完善
我们还要在这个初级版本进一步考虑各种情况然后完善。
考虑1:若调用myCall的对象不为函数时怎么办?抛出错误就好啦。
考虑2:若不为它传参数怎么解决?this即为window。
Function.prototype.mycall=function(obj)
{
if( typeof obj=='function')
{
throw new TypeError('not a function')
}
obj=obj||window
obj.fn=this
obj.fn()
delete obj.fn
}
3.终极实现
但是我们还要考两个问题:
一是参数的问题,因为call方法第一个参数为this要指向的对象,第2-n个参数为要传给function的参数。所以我们可以把这些参数取出来新存放到一个数组当中,然后调用这个函数时解构传入就好啦。
二是返回值,调用call函数默认是返回该函数的执行结果的,所以要保存一下执行结果并返回。
Function.prototype.mycall=function(obj)
{
if( typeof obj=='function')
{
throw new TypeError('not a function')
}
obj=obj||window
obj.fn=this
let args=Array.from(arguments).slice(1)
let result=obj.fn(...args)
delete obj.fn
return result
}
至此,call方法就已经完整实现了一遍。
二、apply的实现
apply和call的区别只是传参不同,apply第二个参数为一个数组,而call第2-n个参数类型不确定,其余都一样,所以在来试试叭~
Function.prototype.myApply=function(obj)
{
if(typeof this!=='function')
{
throw TypeError('这不是一个函数')
} //依旧是类型检查
obj=obj||window
obj.fn=this
let result
if(arguments[1])//存在第二个参数
{
result=obj.fn(...arguments[1]) //解构传参
}else{
result=obj.fn()
}
delete obj.fn
return result
}
三、call、apply总结
所以说call和apply的内部过程就是:
1.给想要绑定的对象设置一个属性,且指向this(即需要调用的对象)
2.通过该对象调用该函数
3.结束调用后删除该属性
四、bind的实现
先来说一下它的实现原理,我们知道bind是返回一个函数但是不执行,什么时候调用什么时候执行,此外,bind有两种运用场景,一是普通函数调用、二是构造函数调用,所以还要判别一下调用它的函数类型。
实现流程大概如下:
bind实现思路:
判断是否是函数调用,若非函数调用抛异常
返回函数。
判断函数的调用方式,是否是被new出来的
new出来的话返回空对象,是new出来的话实例的__proto__指向_this的prototype。
不是则直接绑定this到第一个参数传入的对象上。
Function.prototype.myBind=function(obj)
{
var _this=this
if(typeof _this!=='function')
{
throw TypeError('Not a Function')
}
var args1=Array.prototype.slice.call(1,arguments)
var resultFun=function()
{
var args2=Array.prototype.slice.call(arguments)
var self=this instanceof _this ? this:obj
return _this.apply(self,args1.concat(args2))
}
var temp=function(){
}
temp.prototype=this.prototype
resultFun.prototype=new temp()
return resultFun
}
。
边栏推荐
猜你喜欢
随机推荐
Taro小程序跨端开发入门实战
按键精灵 for ts API 使用
Pyhton面对对象
wps a3格式怎么转换成a4?wps a3格式转换成a4的方法
thinkphp5 if else的表达式怎么写?
MySQL 查询问题?
Upload-labs Pass-02(MIME验证)
The second side of Tencent technical support internship - Tencent's father's luck is so sudden (offer received)
在chrome中呈现RTSP
套接字(Socket)
炒股开户去哪里办理,网上客户经理开户安全吗
目标跟踪实战deepsort+yolov5(上)
【计网】(四)物理层、数据链路层
Unity图文混排实现
巨头杀入的LMFP,是未来正极材料的新归宿?
ArcPy set the unique identification code
php7.4安装ssh2扩展和使用ssh链接sftp上传下载文件
低佣金股票账户是怎么办理的?网上开户安全吗
wsgw login packet capture record
想要精准营销,从学习搭建一套对的标签体系开始丨DTVision分析洞察篇