call 实现
我们知道,call 和 apply 的核心就是改变函数内部 this 的指向
// 以下的 call 和 apply 均指自己实现的函数
那么思路就是让 call 的第一个参数去调用调用 call 的函数,听起来是不是很绕,让我们来实现一下
Function.prototype.call2=function(context){
context=context ? Object(context) : window
let fn = Symbol()
context[fn] = this
let args = [...arguments].slice(1)
let result = context[fn](...args)
delete context[fn]
return result
}
使用 Symbol 是为了和本身属性不冲突
一开始我有一个愚蠢的疑问,既然 fn 这个属性刚被创建马上又被删除,那么我为什么不直接让 this(也就是调用 call 的函数) 去执行呢?
简直是愧为前端哈哈哈,因为如果按照上述做法执行,call 前面的函数在执行时内部的 this 是 window,违背了我们的初衷
我们应该让 context 对象自己去调用函数,这样函数内部的 this 才是 context 对象,注意使用完删除此属性
apply 实现
apply 实现方法和 call 非常类似,代码如下:
Function.prototype.apply2 = function(context,arr){
context = context ? Object(context) : window
let fn = Symbol()
context[fn] = this
let result = arr ? context[fn](...arr) : context[fn]()
delete context[fn]
return result
}