实现js的call-apply-bind函数
因为call-apply-bind 函数底层通过C++实现,只能实现函数的大致功能.我只做了简单的一些边界处理( edge case ),你还可以添加更多的边界处理.
实现call()
// 给所有的函数添加一个FhCall的方法
Function.prototype.FhCall = function(thisArg, ...args){
console.log('args的值:', args); // []
// 问题: 是哪个函数调用了FhCall
// 1.获取需要被执行的函数
var fn = this
// 2.把thisArg转为对象类型(防止传入非对象类型)
// (thisArg!==null && thisArg!=undefined)对传入 0 进行处理
thisArg = (thisArg!==null && thisArg!=undefined) ? Object(thisArg) : window
// 3.调用需要被执行的函数
thisArg.fn = fn
var result = thisArg.fn(...args) // 剩余参数,有没有传参.默认为 []
// 删除对象中的属性名
delete thisArg.fn
// 4.将最终的结果返回出去
return result
}
function abc(num1, num2){
console.log('abc函数被执行', this, num1, num2);
return num1 + num2
}
// 自定义的call
var result = abc.FhCall('abc',1,2,6)
console.log(result);
var result = abc.FhCall('abc')
console.log(result);
实现apply()
Function.prototype.FhApply = function(thisArg, argArray){ // argArray = [] 可以设置默认值进行处理
var fn = this
// (thisArg!==null && thisArg!=undefined)对传入 0 进行处理(edge case)
thisArg = (thisArg!==null && thisArg!=undefined) ? Object(thisArg) : window // 对特殊的忽略显式绑定进行处理
thisArg.fn = fn
// apply()时,注意传过来的数组. 没有传值时是undefined 不能被展开.
// argArray = argArray ? argArray : []
argArray = argArray || []
var result = thisArg.fn(...argArray)
delete thisArg.fn
return result
}
function foo() {
console.log('foo被执行', this);
}
function sum(num1, num2) {
console.log('sum被执行', this);
return num1 + num2
}
foo.FhApply({ name: 'Fhup' })
foo.FhApply(null)
// 剩余的参数放在数组中
var result = sum.FhApply({ age: 18 },[1,2,3])
console.log(result)
实现bind()
Function.prototype.FhBind = function(thisArg, ...argArray){
// 1. 获取需要调用的函数
var fn = this
// 2. 绑定this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
return function(...args){
thisArg.fn = fn
// 3. 将参数进行依次排列(合并)
var finalArgs = [...argArray, ...args]
var result = thisArg.fn(...finalArgs)
delete thisArg.fn
// 4. 返回结果
return result
}
}
function sum (num1, num2){
console.log('sum函数被执行', this, num1, num2);
return num1 + num2
}
var newSum = sum.FhBind('abc',1, 2)
var result = newSum(3, 4)
console.log(result);
// 默认bind()的三种传参方式
// var newSum = sum.bind('aaa', 10, 20, 30)
// newSum()
// var newSum = sum.bind('aaa')
// newSum(10, 20, 30)
// 两个参数依次传入
// var newSum = sum.bind('aaa', 10)
// newSum(20, 30, 40)