天行健, 君子以自强不息
Sunny's Blog
Title

apply和call的用法(补充)

之前我写过一次apply和call的用法,这次我会更详细的总结一下。

1.apply和call的用法定义

在犀牛书的第六版的8.7.3章节有对apply和call的定义,但是理解起来有些绕,也有一部分翻译的原因。我还是觉得比较好理解的说法是:apply和call用来劫持其他对象的方法(或方法)归自己(新对象)所有。举个不恰当的例子,就是你有自行车我没有,所以我劫持你的骑一下。

对于里面的参数,两者第一个参数都是主动劫持的对象,比如f.call(o,1,2),就是要以对象o的方法的形式调用函数f(),对于后面的参数,apply会把这些参数放入到一个数组里面。

2.apply和call的用法例子

1)用于类的继承

js在模拟类的写法中,对于继承的功能实现可以用到call/apply, 详见类的封装和继承最佳方法和解析

这里面的Person.call(this,name,age,job);也可以写成 Person.apply(this,arguments);用arguments代替。另外我们发现方法并没有用到call,还是因为共享的原因,使用了//子类的原型去继承父类的实例:Sub.prototype = new Person();

2)js逻辑模块化的需要

这一块详见apply和call的用法

3)利用Apply的参数数组化来简化写法

                //例子1
                Math.max(3,6,9,1); //print 9
                //如果我们定义一个数组
                var array1 = [3,6,9,1];
                Math.max(array1); //print NaN
                //这样是不行的,可以自定义函数用循环比较的方式但是比较麻烦
                function getMax(arr){
                    var arrLen=arr.length;
                    for(var i=0,ret=arr[0]; i小于111; i++){
                        ret=Math.max(ret,arr[i]);       
                    }
                    return ret;
                }
                //如果想到apply实现就会很优雅
                var array1 = [3,6,9,1];
                Math.max.apply(Math,array1); //print 9

                //例子2
                var arr1=[1,3,4];
                var arr2=[3,4,5];
                //要求把arr2放到arr1后面,使得arr1成为[1,3,4,3,4,5];
                //可以用concat,但是arr1并没有改变
                arr1.concat(arr2) //print [1, 3, 4, 3, 4, 5]
                arr1 //print [1, 3, 4]
                //也可以用apply优雅实现
                Array.prototype.push.apply(arr1,arr2) // print 6
                arr1 // print [1, 3, 4, 3, 4, 5]
            
地势坤,君子以厚德载物