JavaScript中的apply()方法和call()方法使用

来源:互联网 发布:java类的访问权限 编辑:程序博客网 时间:2024/06/06 17:58
1、每个函数都包含两个非继承而来的方法:apply()和call()。 
2、他们的用途相同,都是在特定的作用域中调用函数。 
3、接收参数方面不同,apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来。 
例1: 
window.firstName = "diz"; 
window.lastName = "song"; 
var myObject = { firstName: "my", lastName: "Object" }; 
function HelloName() { 
  console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!"); 

HelloName.call(window); //huo .call(this); 
HelloName.call(myObject); 


运行结果为: 
Hello diz song glad to meet you! 
Hello my Object glad to meet you!


例2: 
function sum(num1, num2) { 
return num1 + num2; 

console.log(sum.call(window, 10, 10)); //20 
console.log(sum.apply(window,[10,20])); //30 


分析:在例1中,我们发现apply()和call()的真正用武之地是能够扩充函数赖以运行的作用域,如果我们想用传统的方法实现,请见下面的代码: 
window.firstName = "diz"; 
window.lastName = "song"; 
var myObject = { firstName: "my", lastName: "Object" }; 
function HelloName() { 
console.log("Hello " + this.firstName + " " + this.lastName, " glad to meet you!"); 

HelloName(); //Hello diz song glad to meet you! 
myObject.HelloName = HelloName; 
myObject.HelloName(); //Hello my Object glad to meet you! 


要想让HelloName()函数的作用域在对象myObject上,我们需要动态创建myObject的HelloName属性,此属性作为指针指向HelloName()函数,
这样,当我们调用myObject.HelloName()时,函数内部的this变量就指向myObjecct,也就可以调用该对象的内部其他公共属性了。 
通过分析例2,我们可以看到call()和apply()函数的真正运用之处,在实际项目中,还需要根据实际灵活加以处理! 
  一个小问题:再看一看函数中定义函数时,this变量的情况 
function temp1() { 
console.log(this); //Object {} 
function temp2() { 
console.log(this); //Window 

temp2(); 

var Obj = {}; 
temp1.call(Obj); //运行结果见上面绿色的注释!!!! 


执行结果与下面的相同: 
function temp1() { 
console.log(this); 
temp2(); 

function temp2() { 
console.log(this); 

var Obj = {}; 
temp1.call(Obj); 


4、bind()方法 
window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
alert(this.color); 

var OSayColor = sayColor.bind(o); 
OSayColor(); //blue 


这里,sayColor()调用bind()方法,并传入o对象,返回了OSayColor()函数,在OSayColor()中,this的值就为o对象。 


其它例子,加深理解
<script>
function cls1()
{
  this.a='123';
}
cls1.prototype.fun1=function()
{
  alert(this.a);
}
function cls2()
{
  this.a='456';
}
var o1=new cls1();
var o2=new cls2();
o1.fun1.apply(o2);
</script>


只有o1对象的类cls1中有fun1这个方法,但是,这时我们需要用o2对象替代o1对象,所以这个时候显示的this.a会是456,
呵呵很神奇吧,换成call方法也是一样的,这两种方法使用的不同点仅仅是参数的使用方法上不同。


apply和call,它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数的方式有所区别:
Function.prototype.apply(thisArg,argArray);
Function.prototype.call(thisArg[,arg1[,arg2…]]);
从函数原型可以看到,第一个参数都被取名为thisArg,即所有函数内部的this指针都会被赋值为thisArg,
这就实现了将函数作为另外一个对象 的方法运行的目的。两个方法除了thisArg参数,都是为Function对象传递的参数。
下面的代码说明了apply和call方法的工作方式:
//定义一个函数func1,具有属性p和方法A
function func1(){
      this.p="func1-";
      this.A=function(arg){
            alert(this.p+arg);
      }
}
//定义一个函数func2,具有属性p和方法B
function func2(){
      this.p="func2-";
      this.B=function(arg){
             alert(this.p+arg);
      }
}
var obj1=new func1();
var obj2=new func2();
obj1.A("byA");     //显示func1-byA
obj2.B("byB");     //显示func2-byB
obj1.A.apply(obj2,["byA"]); //显示func2-byA,其中[“byA”]是仅有一个元素的数组,下同
obj2.B.apply(obj1,["byB"]); //显示func1-byB
obj1.A.call(obj2,"byA");   //显示func2-byA
obj2.B.call(obj1,"byB");   //显示func1-byB
可以看出,obj1的方法A被绑定到obj2运行后,整个函数A的运行环境就转移到了obj2,即this指针指向了obj2。
同样obj2的函数B也可以绑定到obj1对象去运行。代码的最后4行显示了apply和call函数参数形式的区别。
0 0
原创粉丝点击