call()方法和apply()方法用法总结

1. 每一个函数都包含两个非继承而来的方法:call()方法和apply()方法。

2. 相同点:这两个方法的做用是同样的。

都是在特定的做用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的做用域。javascript

通常来讲,this老是指向调用某个方法的对象,可是使用call()和apply()方法时,就会改变this的指向。java

call()方法使用示例:数组

//例1
 <script>
        window.color = 'red';
        document.color = 'yellow';

        var s1 = {color: 'blue' };
        function changeColor(){
            console.log(this.color);
        }

        changeColor.call();         //red (默认传递参数)
        changeColor.call(window);   //red
        changeColor.call(document); //yellow
        changeColor.call(this);     //red
        changeColor.call(s1);       //blue

    </script>

    //例2
    var Pet = {
        words : '...',
        speak : function (say) {
            console.log(say + ''+ this.words)
        }
    }
    Pet.speak('Speak'); // 结果:Speak...

    var Dog = {
        words:'Wang'
    }

    //将this的指向改变成了Dog
    Pet.speak.call(Dog, 'Speak'); //结果: SpeakWang

apply()方法使用示例:markdown

//例1
<script>
        window.number = 'one';
        document.number = 'two';

        var s1 = {number: 'three' };
        function changeColor(){
            console.log(this.number);
        }

        changeColor.apply();         //one (默认传参)
        changeColor.apply(window);   //one
        changeColor.apply(document); //two
        changeColor.apply(this);     //one
        changeColor.apply(s1);       //three

    </script>

    //例2
    function Pet(words){
        this.words = words;
        this.speak = function () {
            console.log( this.words)
        }
    }
    function Dog(words){
        //Pet.call(this, words); //结果: Wang
       Pet.apply(this, arguments); //结果: Wang
    }
    var dog = new Dog('Wang');
    dog.speak();

3. 不一样点:接收参数的方式不一样。

  • apply()方法 接收两个参数,一个是函数运行的做用域(this),另外一个是参数数组。

语法:apply([thisObj [,argArray] ]);,调用一个对象的一个方法,2另外一个对象替换当前对象。app

说明:若是argArray不是一个有效数组或不是arguments对象,那么将致使一个 
TypeError,若是没有提供argArray和thisObj任何一个参数,那么Global对象将用做thisObj。函数

  • call()方法 第一个参数和apply()方法的同样,可是传递给函数的参数必须列举出来。

语法:call([thisObject[,arg1 [,arg2 [,...,argn]]]]);,应用某一对象的一个方法,用另外一个对象替换当前对象。post

说明: call方法能够用来代替另外一个对象调用一个方法,call方法能够将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象,若是没有提供thisObj参数,那么Global对象被用于thisObj。测试

使用示例1:this

 function add(c,d){
        return this.a + this.b + c + d;
    }

    var s = {a:1, b:2};
    console.log(add.call(s,3,4)); // 1+2+3+4 = 10
    console.log(add.apply(s,[5,6])); // 1+2+5+6 = 14 

使用示例2:spa

    <script>
        window.firstName = "Cynthia"; 
        window.lastName = "_xie";

        var myObject = {firstName:'my', lastName:'Object'};

        function getName(){
            console.log(this.firstName + this.lastName);
        }

        function getMessage(sex,age){
            console.log(this.firstName + this.lastName + " 性别: " + sex + " age: " + age );
        }

        getName.call(window); // Cynthia_xie
        getName.call(myObject); // myObject

        getName.apply(window); // Cynthia_xie
        getName.apply(myObject);// myObject

        getMessage.call(window,"",21); //Cynthia_xie 性别: 女 age: 21
        getMessage.apply(window,["",21]); // Cynthia_xie 性别: 女 age: 21

        getMessage.call(myObject,"未知",22); //myObject 性别: 未知 age: 22
        getMessage.apply(myObject,["未知",22]); // myObject 性别: 未知 age: 22

    </script>

四、什么状况下用apply,什么状况下用call

在给对象参数的状况下,若是参数的形式是数组的时候,好比apply示例里面传递了参数arguments,这个参数是数组类型,而且在调用Person的时候参数的列表是对应一致的(也就是Person和Student的参数列表前两位是一致的) 就能够采用 apply , 若是个人Person的参数列表是这样的(age,name),而Student的参数列表是(name,age,grade),这样就能够用call来实现了,也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade));

<script type="text/javascript">  
    /*定义一我的类*/  
    function Person(name,age)  
    {  
        this.name=name;  
        this.age=age;  
    }  
    /*定义一个学生类*/  
    functionStudent(name,age,grade)  
    {  
        Person.apply(this,arguments);  //Person.call(this,name,age);
        this.grade=grade;  
    }  
    //建立一个学生类  
    var student=new Student("zhangsan",21,"一年级");  
    //测试  
    alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);  
    //你们能够看到测试结果name:zhangsan age:21  grade:一年级  
    //学生类里面我没有给name和age属性赋值啊,为何又存在这两个属性的值呢,这个就是apply的神奇之处.  
</script>  

4.        apply的一些其余巧妙用法

细心的人可能已经察觉到,在我调用apply方法的时候,第一个参数是对象(this), 第二个参数是一个数组集合, 在调用Person的时候,他须要的不是一个数组,可是为何他给我一个数组我仍然能够将数组解析为一个一个的参数,这个就是apply的一个巧妙的用处,能够将一个数组默认的转换为一个参数列表([param1,param2,param3] 转换为 param1,param2,param3) 这个若是让咱们用程序来实现将数组的每个项,来装换为参数的列表,可能都得费一会功夫,借助apply的这点特性,因此就有了如下高效率的方法:

 

a)        Math.max 能够实现获得数组中最大的一项

由于Math.max 参数里面不支持Math.max([param1,param2]) 也就是数组

可是它支持Math.max(param1,param2,param3…),因此能够根据刚才apply的那个特色来解决 var max=Math.max.apply(null,array),这样轻易的能够获得一个数组中最大的一项(apply会将一个数组装换为一个参数接一个参数的传递给方法)

         这块在调用的时候第一个参数给了一个null,这个是由于没有对象去调用这个方法,我只须要用这个方法帮我运算,获得返回的结果就行,.因此直接传递了一个null过去

b)        Math.min  能够实现获得数组中最小的一项

一样和 max是一个思想 var min=Math.min.apply(null,array);

c)        Array.prototype.push 能够实现两个数组合并

一样push方法没有提供push一个数组,可是它提供了push(param1,param,…paramN) 因此一样也能够经过apply来装换一下这个数组,即:

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

也能够这样理解,arr1调用了push方法,参数是经过apply将数组装换为参数列表的集合.

一般在什么状况下,可使用apply相似Math.min等之类的特殊用法:

通常在目标函数只须要n个参数列表,而不接收一个数组的形式([param1[,param2[,…[,paramN]]]]),能够经过apply的方式巧妙地解决这个问题!

相关文章
相关标签/搜索