JavaScrtipt动态变换运行时上下文特性,这种特性主要就体现在apply, call两个方法的运用上.
JavaScrtipt中有一个call和apply方法,其作用基本相同,但也有略微的区别。call, apply都属于Function.prototype的一个方法,它是JavaScrtipt引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.既然作为方法的属性,那它们的使用就当然是针对方法的了.这两个方法的作用一样,只是使用方式不同.
在JavaScript中,代码总是有一个上下文对象,代码处理该对象之内. 上下文对象是通过this变量来体现的, 这个this变量永远指向当前代码所处的对象中.javascript对象所有属性都是公开的(public),没私有(private)之说,所以可直接访问javascript对象的属性.
call, apply作用就是借用别人的方法来调用,就像调用自己的一样.
1.call方法
call([thisObj] [,arg1][, arg2][,...][,argN]) thisObj 可选项。将被用作当前对象的对象。 arg1, arg2, , argN 可选项。将被传递方法参数序列。
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
foo.call(thisObj, arg1,arg2,arg3) == thisObj.foo(arg1, arg2, arg3)
(1).简单举例
<input type="button" name="na_but" id="id_but" value="测试call" onclick="testFun()"/> <script type="text/javascript"> var value = "Global Object"; var testFun = function () { /** 没有传递参数 */ window.printValue(); //Global Object printValue.call(window); //Global Object printValue.call(document.getElementById("id_but")); //测试call printValue.call(new objCall()); //call Object testObj.call(this, "hello", "world", "luchunli"); //调用构造方法 } function objCall () { this.value = "call Object"; } function printValue () { alert(this.value); } function testObj () { var str = ""; for(var j = 0 ,end = arguments.length ; j < end ; j++){ str += arguments[j]; } alert(str); //helloworldluchunli } </script>
call函数和apply方法的第一个参数都是要传入给当前对象的对象,及函数内部的this。后面的参数都是传递给当前对象的参数。
<input type="button" name="na_but" id="id_but" value="测试call" onclick="testFun()"/> <script type="text/javascript"> var value = "Global Object"; var testFun = function () { //value : Global Object str : Hello Window printValue.call(window, "Hello Window"); //value : call Object str : Hello printValue.call(new objCall(), "Hello"); //value : 测试call str : input printValue.call(document.getElementById("id_but"), "input"); } function objCall () { this.value = "call Object"; } function printValue (str) { var value = "print value"; alert("value : " + this.value); alert("str : " + str); } </script>
(2).应用进阶
<input type="button" name="na_but" id="id_but" value="测试call" onclick="testFun()"/> <script type="text/javascript"> var value = "Global Object"; var message = "Global Message"; var testFun = function () { var b = new objB(); var a = new objA(); b.setMessage.call(a, "a的消息"); //==>a.setMessage('a的消息'); //message : a的消息; str : This is a; value : call ObjectA printMessage.call(a, "This is a"); } function objA () { this.value = "call ObjectA"; this.setMessage = setMessage; } function objB () { this.value = "call ObjectB"; this.setMessage = setMessage; } function printMessage (str) { alert("message : " + this.message + ";\tstr : " + str + ";\tvalue : " + this.value); } function setMessage (message) { this.message = message; } </script>
2.apply方法
对于apply和call两者在作用上是相同的,但两者在参数上有区别的。
对于第一个参数意义都一样,但对第二个参数:
apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])
同时使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入.
<html> <head> <title>测试call/apply方法</title> <meta http-equiv="Content-Type" content="text/html; charset=gbk"> <script type="text/javascript"> var testFun = function () { testApply("中", "国", "人", "民"); } function testApply (a, b, c, d) { print.call(this, a, b, c, d); print.apply(this, [a, b, c, d]); print.apply(this, arguments); } function print (a, b, c, d) { alert(a + b + c + d); //中国人民 } </script> </head> <body> <input type="button" name="na_but" id="id_but" value="测试apply" onclick="testFun()"/> </body> </html>
由于直接调用testFun方法, 所以在该方法中的上下文对象this就是window对象。
注意:当参数明确时可用call, 当参数不明确时可用apply给合arguments。