call apply bind 的实现的面试中几乎必定出现的一些内容,今天来用一篇文章整理一下这里的内容,加深一下JS基础知识体系。同时文章也被收录到我的《JS基础》专栏中,欢迎大家点击收藏加关注。
call的实现
call()
方法使用一个指定的this
值和单独给出的一个或多个参数来调用一个函数。
let obj = {name:'plus'}
function getName(a){console.log(this.name+'_'+a)
}
getName.call(obj,'666') //plus_666
以上的call可以换成用函数的隐式绑定调用的方法来使用 比如
let obj = {name:'plus',getName: function(a){console.log(this.name+'_'+a)}
}
obj.getName('666') //plus_666
把函数放到要指向的对象中,通过obj.
的隐式调用,就能够改变this的指向
那么根据这个调用方法我们就有思路来实现我们的call方法了
手写call
- 1.在对象中声明一个临时函数,将要执行的函数放到其中
- 2.通过隐式调用
- 3.删除临时函数
- 4.判断传入对象是否为空
_call(fn,...arg) = function(){ if(obj===null||obj===undefined){ //没有指定对象时候 obj =window }obj.temp = fn //临时函数let res = obj.temp(...arg)delete obj.temp //临时函数完成它的任务就要消失了return res
}
//改进版
Function.prototype._call = function(obj,...arg){obj = obj || window //没有指定对象时候 指向windowconst temp = Symbol() //小技巧,Symbol可以用来声明一个对象的属性obj.temp = this //因为call的声明方法是`Function.prototype._call`所以this就是要调用的函数let res = obj.temp(...arg)delete obj.tempreturn res
}
手写apply
apply的实现基本是和call是差不多的,有区别的一点是对于传入的参数,call接收的是多个参数,apply接收的是一个参数数组
- Function.prototype.apply = function(obj,...arg){
+ Function.prototype.apply = function(obj,arg){obj = obj || window //没有指定对象时候 指向windowconst temp = Symbol() //小技巧,Symbol可以用来声明一个对象的属性obj.temp = this //因为call的声明方法是`Function.prototype._call`所以this就是要调用的函数let res = obj.temp(...arg)delete obj.tempreturn res
}
手写bind
bind的实现与call和apply的有点不同,bing中返回的是一个函数,需要对函数进行第二次调用才能真正的执行到函数。我们先来看一下例子。
function getName(a,b,c,d){console.log(`${a} ${b} ${c} ${d}`)
}
let obj = {}
let b1 = getName.bind(obj,1,2)
b1(3,4)
我们可以看到bind的最终调用是分两次实现的,这个实现类似于是柯里化的实现,那么看了bin的使用后我们就可以来手动写出bind了
步骤分为几步:
- 函数中返回一个函数
- 还是和call、apply函数一样设置一个临时函数
- 在返回的函数中,因为是最后一次执行,将所有参数传入,比如arg1传入的是1、2,arg2传入的是3、4。
Function.prototype._bind = function (obj,...arg1) {obj = obj || windowconst temp = Symbol()obj[temp] = thisreturn function(...arg2){obj[temp](...arg1,...arg2) //obj[temp](1,2,3,4)}
}
最后
最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。
有需要的小伙伴,可以点击下方卡片领取,无偿分享