apply() 和 call()

apply()和call()都是属于Function.prototype的一个方法。是JavaScript引擎内在实现的,因为属于Function.prototype,所以每个Function对象实例,也就是每个方法都有call, apply属性.既然作为方法的属性,那它们的使用就当然是针对方法的了.这两个方法是容易混淆的,因为它们的作用一样,只是使用方式不同.
 

相同点:两个方法产生的作用是完全一样的

不同点:方法传递的参数不同

用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

apply:方法能劫持另外一个对象的方法,继承另外一个对象的属性.  
 
  • Function.apply(obj,args)方法能接收两个参数
  • obj:这个对象将代替Function类里this对象  
  • args:这个是数组,它将作为参数传给Function(args-->arguments)  
  • function的方法应用到obj上?
  • call, apply作用就是借用别人的方法来调用,就像调用自己的一样.
call()方法与apply()方法的作用相同,它们的区别仅在于接受参数的方式不同,它的第二个参数是一个参数列表,在使用call()时,传递的参数必须逐个列出来。 
 
apply()实例:
 1 function Person(name,age){
 2           this.name = name;
 3           this.age  age;
 4 }
 5 function Student(name,age,grade){
 6           Person.apply(this.arguments);
 7           this.grade = grade;
 8 }
 9 var student = new Student("123‘,12,"三年级");
10 alert("name:"+student.name+"age:"+student.age+"grade:"+student.grade);
11 //name:123 age:12 grade:三年级

 

 
 
分析:Person.apply(this,arguments);
this:在创建这个对象的时候代表的是student
arguments:["123‘,12,"三年级"];
换句话说就是:用student去执行Person这个类里面的内容在Person 这个类里面存在this.name等之类的语句,这样就将属性创建到了student对象里面。
 
call()的实例:
Person.call(this,name,age);  
 
 
两者的选择:取决于采取哪种给函数传递参数的方式最方便。如果打算直接传入arguments对象,或者函数中先接受到的也是一个数组,那么用apply()肯定更方便,否则选择call();
 
 
一些应用:
1.Math.max:
1 var value = [1,2,3,4,5,6,7,8,9];
2 
3 var max = Math.max.apply(Math.value);

 

 
把Math对象作为apply()的第一个参数,从而正确设置this 的值,然后可以将任何数组作为第二个参数。
 
(因为Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组,但是它支持Math.max(param1,param2,param3…),所以可以根据刚才apply的那个特点来解决 var max=Math.max.apply(null,array),这样轻易的可以得到一个数组中最大的一项(apply会将一个数组装换为一个参数接一个参数的传递给方法)这块在调用的时候第一个参数给了一个null,这个是因为没有对象去调用这个方法,我只需要用这个方法帮我运算,得到返回的结果就行,.所以直接传递了一个null过去 )
 
2.Array.prototype.push
同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN) 所以同样也可以通过apply来装换一下这个数组,即: 
1 var arr1 = new Array("1","2","3");
2 
3 var arr2 = new Array("4","5","6");
4 
5  
6 
7 Array.prototype.push.apply(arr1,arr2);

 

也可以这样理解,arr1调用了push方法,参数是通过apply将数组装换为参数列表的集合.
 
3.Array.prototype.slice.call(arguments)
//能将具有length属性的对象转换成数组。
(附数组转换通用函数):
 1 var toArray = function(s){
 2           try{
 3                      return Array.prototype.slice.call(s);
 4              }catch(e){
 5                                        var arr = [];
 6                                        for(var i = 0, len = s.length; i< len;i++)
 7                                                  arr[i] = s[i];(arr.push(s[i]))
 8                                        return arr;
 9                              }
10 }

 

 
apply()和call()的真正用武之地是能够扩充函数赖以运行的作用域
 1 window.color = "red";
 2 var o = {color:"blue"};
 3 
 4 function sayColor(){
 5           alert(this.color);
 6 }
 7 
 8 sayColor();//red
 9 sayColor.call(this);//red
10 sayColor.call(window);//red
11 sayColor.call(o);//blue

 

使用call()或者apply()来扩从作用域的最大好处,就是对象不需要与方法有任何耦合关系。
 
bind()这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。
 1 window.color = "red";
 2 var o = {color:"blue"};
 3 
 4 function sayColor(){
 5           alert(this.color);
 6 }
 7 
 8 sayColor();//red
 9 sayColor.call(this);//red
10 sayColor.call(window);//red
11 sayColor.call(o);//blue

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。