关于实现call-apply-bind
call-apply-bind可以说是js里经常问到的问题了,如何自己实现一个call/apply/bind方法呢?这里做个记录
1、call
1、首先要每个函数都能调用,就应该给所有函数添加一个myCall方法
Function.prototype.myCall= function() {
}
2、在myCall中要可以去执行调用的函数
例如:
function foo() {
console.log("foo函数被执行", this)
}
foo.myCall(xxx)
在这里,foo函数调用了myCall方法,因此在myCall里应该要拿到foo函数,并且调用。因此在myCall里添加获取foo的代码
Function.prototype.myCall= function() {
// 问题: 得可以获取到是哪一个函数执行了myCall
//获取要执行的函数
var fn = this
fn()
}
3.传入参数,如果传入的thisArg不是个对象,那么就需要进行处理。
Function.prototype.myCall= function(thisArg,...args) {
// 问题: 得可以获取到是哪一个函数执行了myCall
//获取要执行的函数
var fn = this
// 2.对thisArg转成对象类型(防止它传入的是非对象类型)
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
fn()
}
4、调用函数,并将结果传出去
Function.prototype.myCall= function(thisArg,...args) {
// 问题: 得可以获取到是哪一个函数执行了myCall
//获取要执行的函数
var fn = this
// 2.对thisArg转成对象类型(防止它传入的是非对象类型)
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
// 3.调用需要被执行的函数
thisArg.fn = fn
var result = thisArg.fn(...args)
delete thisArg.fn
// 4.将最终的结果返回出去
return result
}
注意:在执行thisArg.fn = fn之后,会给thisArg加上fn,因此在调用完获取结果之后,需要将此增加的删除。
2、apply函数
与call函数实现是类似的思路,不一样的是传入参数的格式不一样,因此对参数格式进行限定就行。实现如下:
// 自己实现myApply
Function.prototype.myApply= function(thisArg, argArray) {
// 1.获取到要执行的函数
var fn = this
// 2.处理绑定的thisArg
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
// 3.执行函数
thisArg.fn = fn
var result
//处理传参
argArray = argArray || []
result = thisArg.fn(...argArray)
delete thisArg.fn
// 4.返回结果
return result
}
3、binb函数
bind函数与call、apply函数的区别是,call/apply返回的是执行后的结果,而bind返回的是替换后的函数。实现思路类似call,区别在于:1、返回函数 2、对参数需要进行合并,实现如下:
Function.prototype.myBind = function(thisArg, ...argArray) {
// 1.获取到真实需要调用的函数
var fn = this
// 2.绑定this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg): window
function proxyFn(...args) {
// 3.将函数放到thisArg中进行调用
thisArg.fn = fn
// 特殊: 对两个传入的参数进行合并
var finalArgs = [...argArray, ...args]
var result = thisArg.fn(...finalArgs)
delete thisArg.fn
// 4.返回结果
return result
}
return proxyFn
}