Function.apply(thisArg: any, argArray?: any)第一个参数用于接受 this 对象,剩余参数为arguments。 所以可以根据思路:
将this挂载到thisArg.fn上
通过thisArg.fn传递参数,获取返回值
删除thisArg.fn
返回
在浏览器中,如果第一个参数为this,那么需要将thisArg设置为window对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Function.prototype.my_apply = function (context, array) { context = Object(context) || window context.fn = this
let result if (!array) { result = context.fn() } else { let args = [] for (let i = 0, len = array.length; i < len; i++) { args.push(`array[${i}]`) } result = eval(`context.fn(${args})`) // context.fn(array[0], array[1]) }
delete context.fn return result }
call 的简易实现
与apply的实现类似,区别在于参数的获取方式不同。
1 2 3 4 5 6 7 8 9 10 11 12 13
Function.prototype.my_call = function (context) { let args = [] context = Object(context) || window// if call(null) then point to window context.fn = this// put current function into context.fn
for (let i = 1, len = arguments.length; i < len; i++) { args.push(`arguments[${i}]`) // push the arguments into args } let result = eval(`context.fn(${args})`) // call function with parameters
Function.prototype.my_bind = function (context) { if (typeofthis !== "function") { thrownewError(`need to be function`) }
let _this = this let args = Array.prototype.slice.call(arguments, 1) // get the rest of arguments
let fTemp = function () {}
let fBound = function () { let bindArgs = Array.prototype.slice.call(arguments) // get the arguments from the return function return _this.apply( thisinstanceof fTemp ? this : context, args.concat(bindArgs) ) // check if it is be a constructor }