Call
call()方法使用一个指定的this值和单独给出一个或者多个参数来调用一个函数,其语法使用如下:
function.call(obj,arg1,arg2,...)
先看如下代码:
function fn(){
console.log(this.name);
}
const obj = {
name:"findly"
}
obj.fn =fn;
obj.fn(); // "findly"
fn.call(obj); // "findly"
由上面代码可见fn.call(obj) === obj.fn(),由this定义可知谁调用方法,则方法内this指向谁,根据这个原则,可以手写实现自己的call方法:
Function.prototype.myCall = function(obj,...args){
//由上面代码可知,fn调用了call方法,所以call内部this指向fn
//所以在这需要将fn方法赋值给传入对象的一个方法,实现obj.fn()
obj.fn = this;
// 调用将obj.fn()返回
return obj.fn(...args)
}
//再次使用上面的fn方法
fn.myCall(obj); // "findly"
如上,实现了一个简单的自定义call方法,但是并没有考虑到一些细节,如当没有对象调用方法时,方法内部的this应当指向window,所以我们要再一次优化上面代码:
Function.prototyp.myCall = function(obj,...args){
//指定this,不传入时为window
obj = obj||window;
//将fn作为传入对象的属性方法
obj._fn = this;
const result = obj._fn(...args);
//再使用之后删除该属性方法
delete obj._fn;
return result;
}
fn.myCall(obj); // "findly"
这样一个较健壮的call自定义就实现了;
apply
apply()方法使用一个指定this值,以及传入数组作为参数,语法如下:
function.apply(obj,[arg1,arg2,...])
由于apply跟call函数仅仅是在接收参数的方式不同。基本原理都是一样,所以实现起来也很简单:
Function.prototyp.myApply = function(obj,args){
//指定this,不传入时为window
obj = obj||window;
//将fn作为传入对象的属性方法
obj._fn = this;
const result = obj._fn(...args);
//再使用之后删除该属性方法
delete obj._fn;
//返回执行结果
return result;
}
fn.myApply(obj,[]); //"findly"
总结:call()和apply()都跟this的指向有关,记住函数内的this指向函数的调用者,就能将其原理掌握就能够自己实现。