理解JavaScript中的call和apply方法

call方法

  总的来说call方法有这几种作用:1.可以借用另一个对象的方法。2.改变this的指向(重要)。3.将arguments数组化。下面详细介绍这三种作用:

  1.可以借用另一个对象的方法:当一个对象需要借用另一个对象的方法时,此时需要用到call方法。

 1     //对象1
 2     var myclass={
 3         getNumbers:function(sum,sum1){
 4             return sum+sum1;
 5         }
 6     };
 7     //对象2
 8     var student={
 9         getDetail:function(){
10             return {name:'张三',habits:'打篮球'}
11         }
12     };
13     //借用 
14     console.log(myclass.getNumbers.call(student,10,200)); //210

这里student对象想要借用myclass对象中的getNumbers方法,需要借用谁的,就将它写在前头。这样就可以实现调用,需要注意的是函数也是对象,同样可以用call方法。

  2.改变this的指向(重要)。

  先来看个例子: 1 用户名:<input type="text" id=“text" value="张三" /> 

1 var value="李四";
2     //函数中默认this指向window
3     function fn1(){
4         console.log(this.value);
5     }
6     fn1();//李四

可以看出此时要想获得表单中的value值是获取不到的。那要如何才能获取到呢,这时call的作用就体现出来了。可以用以下方式获取:

1 function fn1(){
2         console.log(this.value);
3     }
4     fn1.call(document.getElementById('text')); //张三

这个时候this指向input元素对象。

总结一下:call是函数下的一个方法,call方法的第一个参数可以改变函数执行过程中内部this的指向,第二个参数开始就是原来函数的参数列表。

3.将arguments数组化。

  这里先简单介绍一下什么是arguments:arguments是一个数组对象,用于保存函数的参数,准确点说应该是一个伪数组,你可以使用arguments对象在函数中引用函数的参数,它只有在代码运行的时候才起作用。如:

 1 function add() {
 2         var sum = 0,
 3             len = arguments.length;
 4         for (var i = 0; i < len; i++) {
 5             sum += arguments[i];
 6         }
 7         return sum;
 8     }
 9     console.log(add());              // 0
10     console.log(add(1));             // 1
11     console.log(add(1, 2, 3, 4));    // 10

前面说arguments是一个伪数组,那什么是伪数组,伪数组就是它类似于数组,但除了length属性和索引元素之外没有任何数组的属性方法,比如没有push方法。在JavaScript中arguments和通过document获取的dom集合都属于伪数组。

  所以我们很有必要将这些伪数组转换成真数组以便可以使用数组的属性方法。我们可以用call方法将它转换成一个真正的数组:Array.prototype.slice.call(arguments)。利用这个固定用法就可以实现,用一个例子说明一下。

 1 function add(){
 2         var sum=0;
 3         /*arguments.push(10)  //直接这样写则会报错*/
 4         var arr = Array.prototype.slice.call(arguments)
 5         arr.push(10)  
 6         for(var i=0;i<arr.length;i++){
 7             sum+=arr[i]
 8         }
 9         return sum;
10     }
11 
12     var sum = add(1,2,3,4,5)
13 
14     console.log(sum) //25

apply方法

  其实apply方法与call方法的作用是一样的,他们的不同点在于:接收参数的方式不一样。apply方法的第一个参数与call一样,第二个参数是一个参数数组,而call方法传递给函数的参数必须列举出来,还是上面那个例子:

 1     //对象1
 2     var myclass={
 3         getNumbers:function(sum,sum1){
 4             return sum+sum1;
 5         }
 6     };
 7     //对象2
 8     var student={
 9         getDetail:function(){
10             return {name:'张三',habits:'打篮球'}
11         }
12     };
13     //借用 
14     console.log(myclass.getNumbers.call(student,10,20)); //20
15     console.log(myclass.getNumbers.apply(student,[10,10)]); //20

那么我们在什么情况下用apply,什么情况下用call呢?如果参数形式是数组的时候,比如传递参数arguments这种数组类型的,并且他们的参数列表是一一对应的就可以采用apply方法。若参数列表不一致,比如getNumbers的参数列表是(sum,sum1),而student的参数列表是(10,10,20)的,这样就可以用call方法,当然apply的作用不止这些。

apply的其他用法

  1.利用Math.max()函数和Math.min()函数获取数组的最大最小值。我们知道JavaScript中的Math.max()函数,接收的是任意个参数:

console.log(Math.max(1,5,9,2,7,6)) //9

但在很多情况下,我们需要找到数组中的最大元素。想这么写肯定是不行的:

var arr=[2,4,9,1]
    console.log(Math.max(arr))

我们传统的方法是遍历每一个元素:

1 function getMax(arr){
2         for(var i=0,max=arr[0];i<arr.length;i++){
3             max=Math.max(max,arr[i]);
4     }
5     return max;
6     }
7    console.log(getMax([1,3,5,6])); //6

这么写比较低效,换成apply:

1 function getMax2(arr){
2         return Math.max.apply(null,arr);
3        /* return Math.max.call(null,1,3,5,6);*/
4     }
5    console.log(getMax2([1,3,5,6])) //6

这样明显效率要高很多。

  2.将一个数组合并到另一个数组中。我们传统写法是这样的:

 1     var arr1=new Array("1","2","3");
 2     var arr2=new Array("4","5","6");
 3   
 4     function PushArray(arr1,arr2){
 5         for(var i=0;i<arr2.length;i++){
 6             arr1.push(arr2[i])
 7         }
 8         return arr1;
 9     }
10     var result = PushArray(arr1,arr2);
11     console.log(result); //["1", "2", "3", "4", "5", "6"]

换成apply方法需要这么写:Array.prototype.push,可以实现两个数组合并。同样push方法没有提供push一个数组,但是它提供了push(param1,param,…paramN),所以同样也可以通过apply来转换一下这个数组,即

1 var arr1=new Array("1","2","3");
2 var arr2=new Array("4","5","6");
3 Array.prototype.push.apply(arr1,arr2);

apply用的多是因为函数可以接收不限个参数,这样我们就只能使用arguments老管理可变参数,比如max min push join split replace等方法,apply虽然传递的是数组,但是使用的时候是把数组拆开的。

  3.apply不仅仅是使用上面列到的几个函数而已,它还有更加高层的用途:

 1 function add(a, b) {
 2         return a + b;
 3     }
 4 
 5     function add(){
 6         var sum=0;
 7         for(var i=0;i<arguments.length;i++){
 8             sum+=arguments[i]
 9         }
10         return sum;
11     }
12 
13     var sum = add(1,2,3,4,5)
14     console.log(sum); //15
15 
16     //如何计算数组的和
17     var sum2 =  add.apply(null,[1,2,3,4,5])
18     console.log(sum2); //15

有什么不足的请指出。

 

改变

posted @ 2018-04-11 22:12  大海里的一滴水  阅读(433)  评论(0)    收藏  举报