1. 程式人生 > >javascript call和apply的用法

javascript call和apply的用法

存在call和apply的意義

function cat(){
}
cat.prototype={
    food:"fish",
    say: function(){
      console.log("I love "+this.food);
    }
}
var blackCat = new cat;
blackCat.say()  //I love fishI love fish
我們定義了一個建構函式cat,又在cat的原型裡邊定義了一個方法say,
例項化了一個物件blackcat,呼叫原型裡邊的say方法
但是如果我們有一個物件whiteDog = {food:"bone"},我們不想對它重新定義say方法,那麼我們可以通過call或apply用blackCat的say方法:blackCat.say.call(whiteDog);
function cat(){
}
cat.prototype={
    food:"fish",
    say: function(){
      console.log("I love "+this.food);
    }
}
var blackCat = new cat;
blackCat.say()  //I love fishI love fish
var whiteDog = {food:"bone"},
blackCat.say.call(whiteDog) //I love bone

所以,可以看出call和apply是為了動態改變this而出現的,當一個object沒有某個方法,但是其他的有,我們可以藉助call或apply用其它物件的方法來操作

定義

call 和 apply 都是為了改變某個函式執行時的 context 即上下文而存在的,換句話說,就是為了改變函式體內部 this 的指向

apply([thisObj [,argArray] ])
呼叫一個物件的一個方法,另一個物件替換當前物件
apply()方法 接收兩個引數,一個是函式執行的作用域(this),另一個是引數陣列
 //例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();

call([thisObject[,arg1 [,arg2 [,…,argn]]]])
應用某一物件的一個方法,用另一個物件替換當前物件

call()方法 第一個引數和apply()方法的一樣,但是傳遞給函式的引數必須列舉出來

 <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

區別

call物件後面的引數是引數列表,而apply物件後面的引數是陣列

  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 

類陣列

這裡把符合以下條件的物件稱為類陣列

1.具有length屬性

2.按索引方式儲存資料

3.不具有陣列的push,pop等方法
常見類陣列有 arguments,NodeList

(function(){
  Array.prototype.push.call(arguments,4);
  console.log(arguments);//[1, 2, 3, 4]
})(1,2,3)

這樣就往arguments中push一個4進去了
Array.prototype.push 頁可以實現兩個數組合並

同樣push方法沒有提供push一個數組,但是它提供了push(param1,param,…paramN) 所以同樣也可以通過apply來裝換一下這個陣列,即

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

也可以這樣理解,arr1呼叫了push方法,引數是通過apply將陣列裝換為引數列表的集合

再比如我想求類陣列中的最大值

(function(){
  var maxNum = Math.max.apply(null,arguments);
  console.log(maxNum);//56
})(34,2,56);

判斷型別

console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]