1. 程式人生 > >JS中的call和apply函式

JS中的call和apply函式

call 函式

  1. 語法

    obj.call(thisObj,arg[,arg2[,arg3[,...agr]]]);
  1. 簡介

thisObj繼承obj的屬性和方法(obj原型鏈上的屬性和方法不能被繼承),後面的引數會當成obj的引數安裝順序傳遞進去。

  1. 示例

    function animal(type,nickname){
        this.type = type;
        this.nickname = nickname;

        this.sayHello = function(){

            return
'hello'; } } function cat(name,type,nickname){ this.name = name; //cat繼承animal animal.call(this,type,nickname); } console.log(new cat('wsscat','cut','tom')); /* cat { name: 'wsscat', type: 'cut', nickname: 'tom', sayHello: [Function] } */

apply 函式

  1. 語法

    obj.apply(this[,argArray]);
  1. 簡介

apply和call的作用差不多,都可以用來繼承,區別在與apply只有兩個引數,第二個引數必須是陣列或者arguments物件。否則會報TypeError錯誤。如果繼承的物件obj有多個引數,則會吧argArray的引數依次對應obj的每個引數。

  1. 示例

    function animal(type,nickname){
        this.type = type;
        this.nickname = nickname;

        this
.syaHello = function(){ return 'hello'; } } function cat(name,type,nickname){ this.name = name; animal.apply(this,arguments); } console.log(new cat('wsscat','cut','tom')); /* cat { name: 'wsscat', type: 'wsscat', nickname: 'cut', syaHello: [Function] } */

總結

  1. call和apply在功能是相同的。
  2. 相同點在於都是用於物件的繼承,第一個引數都是thisObj.
  3. 不同點在於call可以有多個引數,從第二個引數開始往後的引數會依次傳給被繼承的物件做引數。apply只有兩個引數,第二個引數必須是陣列型別或者arguments物件型別,而且他會把陣列中的元素依次傳遞給被繼承的物件做引數。
  4. 通過以上幾點,我們可以得到如果被繼承的物件只有一個引數的可以使用call,如果被繼承的物件有多個引數的,建議使用apply.

補充

  1. js中可以實現多繼承,只需要呼叫多次call或apply即可。如:

    function animal(type,nickname){
        this.type = type;
        this.nickname = nickname;

        this.syaHello = function(){
            return 'hello';
        }
    }

    function wscat(name,age){
        this.name = name;
        this.age = age;

        this.sayMe = function(){

            return 'my name:' + this.name + ', age:' + this.age;
        }
    }

    function cat(name,age,type,nickname){

        //第一種使用call
        animal.call(this,type,nickname);
        wscat.call(this,name,age);

        //第二種使用apply
        //animal.apply(this,[type,nickname]);
        //wscat.apply(this,[name,age]);
    }

    console.log(new cat('wscat',2,'cat','tom');
    /*
        cat {
          type: 'cat',
          nickname: 'tom',
          syaHello: [Function],
          name: 'wscat',
          age: 2,
          sayMe: [Function] }
    */
  1. 繼承的優化

如果建構函式this綁定了太多的屬性(比如一些共用的函式),示例化後就會照成浪費(因為this裡的屬性和方法例項化後會複製一份給新物件,多個物件之間的屬性和方法互不干涉,對於一些可以共用的方法來就會造成浪費)

所以我們一般把共用的函式都放在原型鏈(prototype)上。但是使用call和apply無法繼承原型鏈上的屬性和方法。

因此我們可以使用混合的而寫法,使用原型鏈和(apply或call)組合的方式進行繼承。

  1. 讓子的原型鏈指向父的示例(父的例項化物件)。如:

    cat.prototype = new animal();
  1. 讓父的屬性建立在子的this上。如:

    animal.call(this[,arg]);
    //animal.apply(this[,argArray]);

具體程式碼如下:


    function animal(type,nickname){
        this.type = type;
        this.nickname = nickname;
    }

    animal.prototype.sayHello = function(){

        return 'hello';
    }

    function wscat(name,age){
        this.name = name;
        this.age = age;
    }  

    //這裡是關鍵,原型鏈只能單繼承,
    //不能同時繼承多個原型鏈,所以要一級一級來。
    wscat.prototype = new animal();
    wscat.prototype.sayMe = function(){

        return 'my name:' + this.name + ', age:' + this.age;
    }

    function cat(name,age,type,nickname){

        animal.call(this,type,nickname);
        wscat.call(this,name,age);
    }

    cat.prototype = new wscat();

    var obj = new cat('wscat',10,'cat','tom');
    console.log(obj);
    //animal { type: 'cat', nickname: 'tom', name: 'wscat', age: 10 }

    console.log(obj.sayHello());//hello

    console.log(obj.sayMe());
    /*
        my name:wscat, age:10
    */