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 || window
context.fn = this
// 由于[...arguments].slice(1),
// 所以就算不传第二个参数,args也是一个空数组,可以被解构
let res = context.fn(...args)
delete context.fn
return 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 || window
context.fn = this
let 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])