Javascript中call的运用本身觉得蛮纠结的,依据文档很好明白,实在很难肯定你是不是真正的明白。 call 要领 应用于:Function 对象 挪用一个对象的一个要领,以另一个对象替代当前对象。 call([thisObj[,arg1[, arg2[, [,.argN]]]]])
参数:thisObj
可选项。将被用作当前对象的对象。 arg1, arg2, , argN
可选项。将被通报要领参数序列。 申明: call 要领能够用来替代另一个对象挪用一个要领。call 要领可将一个函数的对象上下文从初始的上下文转变为由 thisObj 指定的新对象。假如没有供应 thisObj 参数,那末 Global 对象被用作 thisObj。
最基本的明白
自定义一个类,该类有一个要领showTxt,用来显现当前对象的name值。建立一个对象,而且该对象的name值即是test1。运用call要领,使新建立的对象obj增加Class1类的showTxt要领,即把Class1类中的this.showTxt中的this指定成obj,如许obj就有了showTxt要领。弹出”test1″。这个例子很轻易明白。function Class1(){ this.showTxt = function(){alert(this.name)} } var obj = new Object(); obj.name="test1" Class1.call(obj); obj.showTxt();//test1 alert(obj.showTxt);//function(){alert(this.name)}
再看一个轻微深切的明白
建立Class1的实例,让这个实例挪用showTxt要领返回这个实例的name值,由于这个完成没有name值所以返回undefine。function Class1(){ this.showTxt = function(){alert(this.name)} } var class1 = new Class1(); class1.showTxt();//undefined alert(class1.showTxt);//function(){alert(this.name)}
下面就给
Class1
增加个name
值,这时候class1
再挪用showTxt
要领,会返回class1
,这是由于给类增加了name
值,所以实例的name
也由undefine
变成了class1
.function Class1(){ this.name = 'class1';//增加name值 this.showTxt = function(){alert(this.name)} } var class1 = new Class1(); class1.showTxt();//class1 alert(class1.showTxt);//function(){alert(this.name)}
Class1.call(obj)
这个操纵把Class1
中的this.name
,this.showTxt
里的this
替代成了obj
,所以就变成了obj.name='class1'
,所以obj.showTxt
在实行时返回class1
。function Class1(){ this.name = 'class1';//增加name值 this.showTxt = function(){alert(this.name)} } function Class2(){ this.name = 'class2'; } var class2 = new Class2(); Class1.call(class2); alert(class2.showTxt);//function(){alert(this.name)} class2.showTxt();//class1
假如在
Class1.call(obj);
以后再增加obj.name = 'test1'
,末了效果会输入test1
,缘由不言而喻。function Class1(){ this.name = 'class1';//增加name值 this.showTxt = function(){alert(this.name)} } function Class2(){ this.name = 'class2'; } var class2 = new Class2(); Class1.call(class2); class2.name = 'test1';//重定义obj.name值 alert(class2.showTxt);//function(){alert(this.name)} class2.showTxt();//test1
上面的例子
call
的都是一个对象的实例,接下来的案例把对象的实例直接换成函数,看看实行效果会发作哪些变化把
call
要领的第一参数由实例换成函数看看会怎样Class2
是一个function
对象的援用,在实行Class1.call(Class2)
时this.showTxt
里的this
被替代成了Class2
。如许Class2
就有了showTxt
要领,Class2.showTxt()
实行时会返回Class2.name
的值,由于Class2
并未定义name
值,所以会返回undefined
。Class2
函数里的this.name
是由Class2
建立实例的name
值,并非Class2.name
,这两个值有时会让我含糊。function Class1(){ this.showTxt = function(){alert(this.name)} } function Class2(){ this.name = 'class2'; } Class1.call(Class2); alert(Class2.showTxt);//function(){alert(this.name)} Class2.showTxt();//undefined
接着看下面的例子
class1.showTxt.call(class2);
之所以会返回class2是由于function(){alert(this.name)}
这里的this
被call
指定成了class2
,变成了alert(class2.name)
,所以会返回class2
。alert(class2.showTxt)
返回undefined
,申明并未定义class2.showTxt
要领。function Class1(){ this.showTxt = function(){alert(this.name)} } function Class2(){ this.name = 'class2'; } var class1 = new Class1(); var class2 = new Class2(); class1.showTxt.call(class2);//class2 alert(class2.showTxt);//undefined
由于并为给
class2
增加showTxt
要领,所以提醒该毛病。假如在这个挪用之前增加Class1.call(class2);
这个挪用就OK了Class1.call(class2);class2.showTxt();//class1
这个例子都邑返回
undefined
function Class1(){ this.showTxt = function(){alert(this.name)} } function Class2(){ this.name = 'class2'; } var class1 = new Class1(); class1.showTxt.call(Class2);//undefined alert(Class2.showTxt);//undefined
在运用call时假如挪用函数里没有
this
会怎样function add(a,b){ alert(a+b); } function sub(a,b){ alert(a-b); } add.call(sub,3,1);//4
效果返回4,
add.call(sub,3,1)
在实行过程当中,sub
做为add
函数中this
的替代品涌现,然则由于add
里没有用到this
,所以sub
函数直接疏忽,所以效果是4。
所以现实实行以下:返回4。function add(a,b){ alert(a+b); } add(3,1);//4
不错,接下来再明白一个奇异的情势
function f1(){ alert(1); } function f2(){ alert(2) } var f3 = f1.call; f1.call(f2);//1 f3.call(f2);//2
f1.call(f2);
比较好明白,假如不明白看上边的case,但怎样明白f3.call(f2)
会返回2呢,为了轻易明白举行一下等效变化为f1.call.call(f2)
,这时候会发明现实上是f1.call
要领call
挪用了f2
,那f1
怎样又会有call
要领呢?call
,apply
都属于Function.prototype
的一个要领,它是JavaScript
引擎内涵完成的,由于属于Function.prototype
,所以每一个Function
对象实例,也就是每一个要领都有call
,apply
属性。
在明白f1.call.call(f2)
时我们起首要知道call
要领究竟是怎样实行的,如许才f1.call.call(f2)
怎样实行。
援用JK写的一个用apply完成call的要领:function jsCall(oThis){//这里的jsCall就是Call var argsNew = []; for(var i=1;i<arguments.length;i++){ argsNew.push(arguments[i]); } return this.apply(oThis,argsNew); } Function.prototype.jsCall = jsCall;
或简写成
function jsCall(oThis){//这里的jsCall就是Call var argsNew = [].slice.call(arguments,1) return this.apply(oThis,argsNew); } Function.prototype.jsCall = jsCall;
如许就得到了一个和
call
一样功用的jsCall
, 接下来构建两个函数f1
,f2
function f1(a){ alert([this,a,'f1']); } f1(11);//[object Window],11,f1 function f2(a){ alert([this,a,'f2']); } f2(22);//[object Window],22,f2
用
jsCall
把f1
中的this
替代成f2
function f1(a){ alert([this,a,'f1']); } function f2(a){ alert([this,a,'f2']); } f1.jsCall(f2,11);//function f2(a){alert([this, a, "f2"]);},11,f1
实行效果发明
[object Window]
被替代成f2
函数function jsCall(oThis){//这里的jsCall就是Call var argsNew = [].slice.call(arguments,1) return this.apply(oThis,argsNew); } Function.prototype.jsCall = jsCall; function f1(a){ alert([this,a,'f1']); } function f2(a){ alert([this,a,'f2']); } f1.jsCall.jsCall(f2,11);//11,,f2
在实行
f1.jsCall.jsCall(f2,11);
时返回11,,f2
,为何会返回这个效果,重点来了:)f1.jsCall
要领:alert(f1.jsCall); //返回 //function jsCall(oThis) { // var argsNew = [].slice.call(arguments, 1); // return this.apply(oThis, argsNew); //}
所以
f1.jsCall.jsCall
能够替代成jsCall.jsCall
看一下实行效果function jsCall(oThis){//这里的jsCall就是Call var argsNew = [].slice.call(arguments,1) return this.apply(oThis,argsNew); } Function.prototype.jsCall = jsCall; function f1(a){ alert([this,a,'f1']); } function f2(a){ alert([this,a,'f2']); } jsCall.jsCall(f2,11);//11,,f2
接着剖析
jsCall
在实行的过程当中,return this.apply(oThis,argsNew);
里的this
被替代成了f2
,11
做为参数传给了(oThis,argsNew)
,变成了f2.apply(11);
function jsCall(oThis){//这里的jsCall就是Call var argsNew = [].slice.call(arguments,1) return this.apply(oThis,argsNew); } Function.prototype.jsCall = jsCall; function f1(a){ alert([this,a,'f1']); } function f2(a){ alert([this,a,'f2']); } f2.apply(11);//11,,f2
返回效果跟
f1.jsCall.jsCall(f2,11)
一样。
回过头来看function f1(){ alert(1); } function f2(){ alert(2) } var f3 = f1.call; f1.call(f2);//1 f3.call(f2);//2
如许就不难明白
f1.call.call(f2)
完成时,f1.call
实行过程当中call
中的this
被f2
替代成了f2.call();
由于f2
里没有this
的援用所以实行效果是2.f2.call()//2
须要十分注意的是f1.call
是要领,f1
是函数对象,这两者在call
时是有区分的。