Function.prototype.applyFn = function (targetObject, argsArray) {
if (typeof argsArray === 'undefined' || argsArray === null) {
argsArray = []
}
if (typeof targetObject === 'undefined' || targetObject === null) {
targetObject = window
}
targetObject = new Object(targetObject)
const targetFnKey = Symbol() // 防止属性名重复
targetObject[targetFnKey] = this
const result = targetObject[targetFnKey](...argsArray)
delete targetObject[targetFnKey]
return result
}
测试下结果:
const obj = {
a: 1
}
var a = 2
function logA() {
console.log(this.a)
}
logA() // 2
logA.apply(obj) // 1
logA.applyFn(obj) // 1
代码不难,函数体内this指向调用applyFn的函数。为了将该函数体内的this绑定在targetObject上,此处采用了隐式绑定的方法:targetObject[targetFnKey](...argsArray)。
这里存在一个问题:如果targetObject对象本上有targetFnKey这样的属性,那么在使用applyFn函数时,原有targetFnKey属性值就会被覆盖,之后被删除。解决方案是使用ES6 Symbol()来保证键的唯一性,或者使用Math.random()实现独一无二的键,此处采用的是使用symbol()来处理。