本文从js
代码的角度去实现apply/call/bind
的主要功能
不会过多的考虑边界情况
, 只是记录一下功能实现的大体思路
如果对你有所帮助或启发, 请帮忙点个赞哦~ Thanks♪(・ω・)ノ
Apply实现
传入两个参数, 第一个参数作为传入的this
对象被绑定
第二个参数需要是数组或者类数组形式的数据
function foo(num1,num2){
console.log('foo被执行...',this);
//foo被执行... String {'apply'}
return num1+num2
}
//系统的apply方法
const result = foo.apply('apply',[4,5])
console.log('result',result); //result 9
根据apply
方法的功能, 具体实现如下:
// 使用js模拟apply函数的实现
Function.prototype.moniApply = function(thisArg,args){
//1.获取需要被执行的函数
const fn = this //这里的this是根据默认绑定自动获取到的
//2.处理边界情况 undefined和null
if(thisArg===null || thisArg===undefined) thisArg = window
//3.判断参数类型进行相关转化
const argType = typeof(thisArg)
if(argType!=='object'){
// thisArg = Object(thisArg) //或者直接用Object包裹
switch(argType){
case 'number':
thisArg = new Number(thisArg)
break;
case 'string':
thisArg = new String(thisArg)
break;
case 'boolean':
thisArg = new Boolean(thisArg)
break;
default:
break;
}
}
thisArg.fn = fn
//4.处理参数个数的临界情况
args = args || []
const result = thisArg.fn(...args)
delete thisArg.fn
//5.返回结果
return result
}
Call实现
根据MDN定义, call()
方法使用一个指定到的this
值
和单独给出的一个或多个参数来调用一个函数
该方法接收的是一个参数列表
function foo(num1,num2){
console.log('foo被执行...',this,num1,num2);
// foo被执行... String {'call'} 4 undefined
return num1+num2
}
//系统的call方法
foo.call('call',4) // NaN
call
方法和apply
的功能类似, 只是第二个参数接收数据类型有差异
// 使用js模拟call函数的实现
Function.prototype.moniCall = function(thisArg,...args){
//1.获取需要被执行的函数
const fn = this
//2.处理边界情况 undefined和null
if(thisArg===null || thisArg===undefined) thisArg = window
//3.判断参数类型进行相关转化
const argType = typeof(thisArg)
if(argType!=='object'){
switch(argType){
case 'number':
thisArg = new Number(thisArg)
break;
case 'string':
thisArg = new String(thisArg)
break;
case 'boolean':
thisArg = new Boolean(thisArg)
break;
default:
break;
}
}
//4.调用需要被执行的函数
thisArg.fn = fn
thisArg.fn(...args)
//5.最终结果返回
const result = thisArg.fn(...args)
if(result){
delete thisArg.fn //尽量模拟真实call返回的格式
return result
}
}
function foo(num1,num2){
console.log('foo被执行...',this,num1,num2);
// foo被执行... String {'monicall', fn: ƒ} 1 2
return num1+num2
}
const result = foo.moniCall('monicall',1,2,3)
console.log('result',result); //result 3
Bind实现
首先, bind()
方法会返回一个新的函数
这个新函数的 this
被指定为 bind()
的第一个参数
而其余参数将作为新函数的参数,注意参数是可以累计传递的
function sum(num1,num2,num3,num4,num5,num6){
console.log('sum被执行',this,num1,num2,num3,num4,num5,num6);
}
const bind = sum.bind('bind',1,2)
bind(3,4) //sum被执行 String {'bind'} 1 2 3 4
注意在实现bind
函数的时候, 会返回一个新的函数
Function.prototype.moniBind = function(thisArg,...args){
//1.获取到真实需要调用的函数
const fn = this
//2.处理边界情况 undefined和null
if(thisArg===null || thisArg===undefined) thisArg = window
//3.判断参数类型进行相关转化
const argType = typeof(thisArg)
if(argType!=='object'){
switch(argType){
case 'number':
thisArg = new Number(thisArg)
break;
case 'string':
thisArg = new String(thisArg)
break;
case 'boolean':
thisArg = new Boolean(thisArg)
break;
default:
break;
}
}
//4.返回一个新的代理函数
return function proxyFn(...proxyArgs){
thisArg.fn = fn
const finalArgs = [...args,...proxyArgs] //做参数累计传递的优化
const result = thisArg.fn(...finalArgs)
delete thisArg.fn
return result
}
}
const moniBind = sum.moniBind('moniBind',1,2)
moniBind(3,4,5) //sum被执行 String {'moniBind', fn: ƒ} 1 2 3 4 5 undefined