call实现
思路:
(1)判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。 (2)判断传入上下文对象是否存在,如果不存在,则设置为 window 。 (3)处理传入的参数,截取第一个参数后的所有参数。 (4)将函数作为上下文对象的一个属性。 (5)使用上下文对象来调用这个方法,并保存返回结果。 (6)删除刚才新增的属性。 (7)返回结果。
代码:
Function.prototype._call = function (context) {if(typeof this !== "function"){return}let args = [...arguments].slice(1)context = context || windowcontext.fn = this// 由于[...arguments].slice(1),// 所以就算不传第二个参数,args也是一个空数组,可以被解构let res = context.fn(...args)delete context.fnreturn res}
apply实现
思路:
(1)判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。 (2)判断传入上下文对象是否存在,如果不存在,则设置为 window 。 (3)处理传入的参数,截取第一个参数后的所有参数。 (4)将函数作为上下文对象的一个属性。 (5)使用上下文对象来调用这个方法,并保存返回结果。 (6)删除刚才新增的属性。 (7)返回结果。
代码:
Function.prototype._apply = function (context) {if (typeof this !== "function") {console.error("type error");return}let args = arguments[1]context = context || windowcontext.fn = thislet res = null// 当没有传入第二个参数时,// 由于args不能迭代,也就是不能解构,所以要判断一下if (args) {res = context.fn(...args)} else {res = context.fn()}return res}
测试:
let obj = {name: "mikasa"}let user = {getName(value) {console.log(value);console.log(this.name);}}// 成功输出user.getName._call(obj, 111)user.getName._apply(obj, [111])

