步骤
- 首先明确call函数是定义在Function.prototype上的,为所有Function类型的对象所共享。现自定义Function.prototype.myCall.
传入参数:
- 1、context表示谁来调用这个原函数
- 2、...args用三点运算符直接将后面传入的参数解析成数组
- 确定由谁来调用函数,命名为new_this;若没有传入要绑定的对象,默认绑定window对象
- 把方法作为对象的属性绑定给new_this,但是注意,也许原有属性就有func这个属性,为了避免冲突,用symbol
- 执行当前函数,并获取返回值
- 删除我们绑定的Symbol(func)属性,以免污染new_this的属性
- 返回第3步得到的返回值
// 传递参数从一个数组变成逐个传参,
// 不用...扩展运算符也可以用arguments代替
Function.prototype.myCall = function(context,...args){
// 不需要判断类型,因为myCall定义在Function.prototype上
if(typeof this !== 'function'){
throw new TypeError(`${this} is not a function!`)
}
// 1、确定要绑定的对象,即最终谁来调用函数,命名为new_this;
// 若没有传入要绑定的对象,默认绑定window对象
const new_this = context || window
// 2、把方法作为对象的属性绑定给new_this,但是要注意,也许原有属性就有func,
// 为了避免冲突,这里用symbol
const func = Symbol('func')
// 由于这里func是Symbol变量不再是字符串,所以不能再用new_this,
// func而是要用中括号获取属性
new_this[func] = this
// 3、执行当前函数,并获取返回值
const res = new_this[func](...args)
// 4、删除我们绑定的Symbol(func)属性,以免污染new_this的属性
delete new_this[func]
// 5、返回第三步得到的返回值
return res
}
测试如下
var person = {
name:'tom',
age:12
}
function getInfo(a,b){
var sum = a + b
console.log('name:',this.name,'age:',this.age,'sum':sum)
}
getInfo.myCall(oerson,1,1) // name:tom,age.12.sum:2