this, Function.apply 及Function.call
考虑以下这段代码:
< input type = " button " id = " btnSubmit " value = " Click me! " /> 2
3
< script language = " javascript " type = " text/javascript " > 4
function ButtonManager(buttonId, message)5
{6
this ._message = message;7
document.getElementById(buttonId).onclick = this .ShowMessage; 8
} 9
10
ButtonManager.prototype.ShowMessage = function ()11
{12
alert( this ._message);13
} 14
15
var btnManager = new ButtonManager( " btnSubmit " , " Hello! " );16
</ script >
按预想的意图,当点击按钮时,应当会弹出"Hello!",但上面的代码运行,却弹出"undefined"。问题出在哪里呢?在12行设个断点,对它进行调试,发现this竟然是指向btnSubmit,如果是这样的话,那就难怪会弹出"undefined",因为btnSubmit本身并没有定义_message,而我们所期望的this应当是指向 btnManager,我们真正期望调用的方法其实是btnManager.ShowMessage()。
事实上,这是与Javascript的语法和运行机制有关的,当ShowMessage真正调用前,this的指向是不明确,而只有在运行里,this的指向会由运行时来决定。
那么有没有什么方法来正确实现上述意图呢?答案是肯定的,首先要可以看下面的代码:
var x = 10 ;2
var o = {x: 15 } ;3
function foo()4
{5
alert(this.x);6
} 7
8
foo.call(o); 运行之后,我们会发现结果会分别是10和15。这似乎有点疑惑了,当然关键点肯定就是那个Call了。
Javascript 中的function本身也是一个object,它本身就会有tostring(),call(),apply()几个附加方法。这个 function.call的意义就在于,当调用时它时,运行时会把它的第一个参数替换掉function的this指向。
当调用foo()时,this是指向window的,而事实上,所有的全局变量就是window的属性。foo.call(o)时,this是指向o的。
理解了function.call的作用,当解决上面的问题就不难了。
< input type = " button " id = " btnSubmit " value = " Click me! " /> 2
3
< script language = " javascript " type = " text/javascript " > 4
function ButtonManager(buttonId, message)5
{6
this ._message = message;7
document.getElementById(buttonId).onclick = createDelegate( this , this .ShowMessage);8
} 9
10
ButtonManager.prototype.ShowMessage = function ()11
{12
alert( this ._message);13
} 14
15
function createDelegate(object, method)16
{17
var delegate = function ()18
{19
method.call(object);20
} 21
return delegate;22
} 23
24
var btn = new ButtonManager( " btnSubmit " , " Hello! " );25
26
</ script >
我们加入一个createDelegate的funciton,它的作用类似为onclick事件创建一个事件委托对象。现在,代码可以正常工作了。
另外,function.apply()和function.call()基本功能是一样的,但apply却可以授受两个参数,而且第二个参数必须是一个数组。
var o = {x: 10 } ;2
function f(message)3
{4
alert(message + ( this .x * this .x));5
} 6
7
function g(object, func)8
{9
var args = [];10
for ( var i = 2 ;i < arguments.length;i ++ )11
{12
args.push(arguments[i]);13
} 14
func.apply(object,args);15
} 16
17
g(o,f, " result : " );
基于apply的这个特点,apply比call使用更加广泛,在javascript中的继承中,apply的使用也是必不可少的
浙公网安备 33010602011771号