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的方式巧妙地解決這個問題!

相關文章
相關標籤/搜索