先看一个例子,一个是在全局变量中调用test函数,另一个是在people对象中调用test函数。
var name = 'tony';
let people = {
name:'anny',
test:function(){
console.log(this.name);
}
}
function test(){
console.log(this.name)
}
test(); //out:tony
people.test(); //out:anny
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
我们只需要模仿《在对象中调用函数》
即可实现 call 与 apply。
Function.prototype.myCall = function (context, ...msg) {
//这里的 this 就是代表上面例子(前言)中的 test() 函数
let _this = this;
//我们需要判断一下 this 是否是一个函数,否则就抛出错误
if (typeof _this !== 'function') {
throw new TypeError(`${_this.name}.call is not a function`)
}
//获取传入的对象
//如果没有传入对象,则取全局对象 window
//你可以将此处的对象想象成上面例子(前言)中的 people 对象
context = context || window;
//将函数保存到对象的属性中
context.test = _this;
//获取其他传入的值
let otherMsg = msg;
//还记得中心思想吗?
//实现《在对象中调用函数》
/**
* 如:people.test()
*/
//这里需要记录下该函数是否有返回值
let result = context.test(...otherMsg);
//删除函数
context.test = null;
//返回函数的返回值
return result;
}
test.myCall(people)
Function.prototype.myApply = function (context, msg) {
//这里的 this 就是代表上面例子(前言)中的 test() 函数
let _this = this;
//我们需要判断一下 this 是否是一个函数,否则就抛出错误
if (typeof _this !== 'function') {
throw new TypeError(`${_this.name}.call is not a function`)
}
//获取传入的对象
//如果没有传入对象,则取全局对象 window
//你可以将此处的对象想象成上面例子(前言)中的 people 对象
context = context || window;
//将函数保存到对象的属性中
context.test = _this;
//获取其他传入的值
let otherMsg = msg;
//还记得中心思想吗?
//实现《在对象中调用函数》
/**
* 如:people.test()
*/
//这里需要记录下该函数是否有返回值
let result = context.test(...otherMsg);
//删除函数
context.test = null;
//返回函数的返回值
return result;
}
test.myApply(people)
apply和call差不多,只是传入的参数不同,如:
let people1 = {
name:'bolo'
}
function test1(age,sex){
console.log(this.name);
console.log(age);
console.log(sex);
}
test1.myCall(people1,20,'男')
test1.myApply(people1,[20,'男'])
Function.prototype.myBind = function (context, ...msg) {
//获取函数 如:test()
let _this = this;
//我们需要判断一下 this 是否是一个函数,否则就抛出错误
if (typeof _this !== 'function') {
throw new TypeError(`${_this.name}.call is not a function`)
}
//返回一个函数
return function(...msg2){
//执行如test()函数
//并将 test()函数返回值返回
return _this.myCall(context,...msg,...msg2);
}
}
/**
* let bindF = test1.myBind(people1)
* bindF(20,'男');
*/
let bindF = test1.myBind(people1,20,'男')
bindF();