1、实现call()
js提供的call方法可以实现函数内this指向的改变,我们可以看下面这个例子
1 2 3 4 5 6 7 8
| const obj={ a:'1' } function fn(){ console.log(this.a) } fn() fn.call(obj)
|
可以看到使用call我们可以将函数中的this强制指向obj对象。
下面我们来自己实现这个函数,我们都知道函数fn如果直接执行,则this是指向window的,而通过对象来调用一个函数,那么这个函数的this是指向这个对象的,那么我们就可以对上面的obj进行改造,将函数赋给obj,然后通过obj来调用这个函数即可
1 2 3 4 5 6 7
| const obj={ a:'1', fn:function(){ console.log(this.a) } } obj.fn()
|
那么上面两个结合我们就可以写成下面这三部,先将函数给对象再通过对象调用,然后在删去这个函数即可
1 2 3
| obj.fn=fn obj.fn() delete obj.fn
|
实现:
1 2 3 4 5 6 7
| Function.prototype.mycall=function(context=window){ const obj=context||window obj.fn=this const result=obj.fn() delete obj.fn() return result }
|
当然我们的call还是可以给函数传参的,我们可以改写成下面这个样子
1 2 3 4 5 6 7
| Function.prototype.mycall=function(context=window,...args){ const obj=context||window obj.fn=this const result=obj.fn(...args) delete obj.fn return result }
|
这样就大功完成啦下面就可以来测试啦
1 2 3 4 5 6 7 8 9
| const obj={ a:'2' } function fn(name,age){ console.log(name) console.log(age) console.log(this.a) } fn.mycall(obj,'name',12)
|
2、实现apply()
apply的实现和call的实现类似,只不过一个传递的参数形式不同而已
1 2 3 4 5 6 7 8 9 10 11 12
| Function.prototype.myapply=function(context=window,args){ let result; const obj=context||window obj.fn=this if(Array.isArray(args)){ result=obj.fn(...args) }else{ result=obj.fn() } delete obj.fn return result }
|
测试就跟上面的call一样的啦 这边就不贴了。
3、实现bind
bind的作用是返回一个新的函数,且这个函数的this指向已被改变,我们可以通过call或者是apply来完成,通过闭包返回一个函数来实现
1 2 3 4 5 6
| Function.prototype.mybind=function(context=window,...args){ const that=this return Function F(...args2){ return that.apply(context,args.concat(args2)) } }
|
由于bind后产生的函数除了可以直接调用还会用作构造函数使用,所以我们在这里加个对他的判断,如果是构造函数,则直接返回实例对象。
1 2 3 4 5 6 7 8 9 10
| Function.prototype.mybind=function(context=window,...args){ const that=this const obj=context||window return Function F(...args2){ if(this instanceof F){ return new that(...args,...args2) } return that.apply(obj,args.concat(args2)) } }
|
我们加一层判断就可以啦,如果是构造函数则直接用原本的函数进行new就行啦
最后更新时间:
感谢阅读