众所周知,call,apply以及bind函数的实现在前端面试手写题中经常考到,这个体现js基本功的一个重要考量,那么我们今天就来实现一下对应的模拟源码(附上详解)。
前期准备
准备好一个对象以及一个函数,准备来将func的this指向到obj的对象中。
let obj = {
name:'老周'
}
function func(age,gender){
console.log("名字为"+this.name)
console.log("我的年龄是"+age)
console.log("我的性别是"+gender)
}
源码模块
call函数模拟(第二,三...参数是func函数运行时传入的参数)
function myCall(context,...args){
// 1.首先在context上下文对象(此处指的是上文的obj)中添加入func这个键值对。
// this则是实例化引用对象,也就是最后调用myCall方法的func。
context.func = this
// 2.执行context中的func函数并传入func设定的形参
const res = context.func(...args)
// 3.将第一步添加的func键值对删除,恢复原样,不要改变obj的原有属性
delete context.func
// 4.最后将func的执行结果返回出去
return res
}
// 为了让全局的func函数能够以函数的形式调用该api,我们将我们写出的myCall方法放进Function的原型链中成为一个属性。
Function.prototype.myCall = myCall
运用一下并打印结果
func.myCall(obj,"18","男") // 名字为老周 我的年龄是18 我的性别是男
apply函数模拟
第一个参数是context上下文 传入的第二个参数是一个数组,也就是将要调用的函数func的实参数组集
function myApply(context,args){
context.func = this
const res = context.func(...args)
delete context.func
return res
}
Function.prototype.myApply = myApply
运用一下并打印结果
func.myApply(obj,["20","男"]) // 名字为老周 我的年龄是20 我的性别是男
bind函数模拟
此时我们就不再向上面一样重复代码了,可以套用上边的call函数。
我们知道,调用bind方法后,func是不会自动执行的,需要再次调用才能执行,所以我们这个模拟方法将return 出去一个函数
function myBind(context,...args){
//因为此时myBind函数的内部的this指针无法让外部实例读取到,所以我们定义f变量接收this,并在return 函数之中将f变量暴露出去。
const f = this
return function(){
// console.log(this) 此处打印出来就是window全局对象,并非func
return f.myCall(context,...args)
}
}
Function.prototype.myBind = myBind
运用一下并打印结果
func.myBind(obj,"22","男")() // 名字为老周 我的年龄是22 我的性别是男
以上就是本文的主要内容,期待学习的小伙伴认真观看并理解其中的要点,文中有缺陷的地方也欢迎评论区留言并改进。