看到该文章,表示你对call和apply的使用已经有所了解,call和apply的调用都是用于改变函数的this指向的。
call模拟实现
call和apply功能一样,我们就不一一举例,这里以call的正常使用和模拟实现为例。
示例:call的正常使用
var key = "windowK";
var obj = {
key : "objK"
}
function fn(name,age){
console.log("name="+name+" ; age="+age+" ; this.key="+this.key);
}
fn("Lucy", 20); //"name=Lucy ; age=20 ; this.key=windowK"
fn.call(obj,"Lucy",20); //"name=Lucy ; age=20 ; this.key=objK"
如何修改函数的this指向呢?我们知道函数以对象的形式调用时,this指向该对象。由此可以想到把函数赋值给对象(obj)的新属性(fn),然后调用该对象(obj)的属性(fn),函数的this自然指向对象(obj)。但这样操作的话对象会增加新的属性,该属性只是为改变this指向添加的,并无实际意义,所以调用完对象属性方法后,需要删除该对象属性。
故call模拟的步骤可以分为3步:
1)将函数设为对象的属性;
2)执行该函数;
3)删除该函数;
示例:call的模拟实现
Function.prototype.mCall = function(newObj){
newObj = newObj||window;
newObj.fn = this;
var args = [];
for(var i=1,ln=arguments.length; i<ln; i++){
args.push('arguments['+i+']');
}
eval('newObj.fn('+args+')');
delete newObj.fn;
}
fn.mCall(obj,"Lucy",20); //"name=Lucy ; age=20 ; this.key=objK"
apply模拟实现
apply和call的实现机制相似,前面已详细分析了call的模拟实现,对apply不再进行详细分析,直接看apply的模拟实现代码吧。
Function.prototype.mApply = function(newObj,paramArr){
newObj = newObj||window;
newObj.fn = this;
if(paramArr){
var args = [];
for(var i=0,ln=paramArr.length; i<ln; i++){
args.push('paramArr['+i+']');
}
eval('newObj.fn('+args+')');
}else{
newObj.fn();
}
delete newObj.fn;
}
fn.mApply(obj,["Lucy",20]); //name=Lucy ; age=20 ; this.key=objK