閒聊js中的apply、call和arguments

         JavaScript提供了apply和call兩種調用方式來肯定函數中的this的指向,在現實編碼中,我確實面試

不多接觸到這兩個方法。但很無奈,不少面試題都要考這兩種方法,我又沒怎麼用到,因此咱們先來數組

閒聊下他們到底有什麼用和到底怎麼用。
         咱們先來聊一下apply的用法吧,它是用來改變函數的指向的,說白了,就是指向了別的函數的做用域。
瀏覽器

例如看一下下面這個例子。app

var A={
    name:"我是小A",
    fun:function(){
        console.log("你們好! "+this.name)
    }
}

var B = {
    name:"我是小B"
}

A.fun();           //你們好! 我是小A
A.fun.apply(B);    //你們好!  我是小B

能夠看出來,當咱們使用了apply將引用指向了B時,A調用fun時並非調用自己中的name  而是調用了B中的那麼;函數

但若是咱們在調用函數中並沒用引用到this,那麼是否是說apply就失去了意義?再來看一下下面的例子this

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你們好! "+this.name+" 我有"+num+"張"+money+"塊")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];

A.fun.apply(B,monies);    //你們好! 我是小B 我有10張20塊

能夠看出:apply中編碼

  第一個參數爲thisObject,調用時採用傳入的thisObject代替函數體中this的指向spa

 第二個參數傳入一個數組,函數會用數組的值取代「參數列表"。prototype

 

 

      這裏聊一下monies,就要說到參數列表,固然咱們會想到arguments,在這裏插入聊一下arguments。網code

上arguments是具備數組某些特性的‘類數組‘(僞數組);其實JS並無重載函數的功能,可是auguments對象

可以模擬重載。每一個函數都有一個Arguments對象實例arguments,它引用着函數的實參,能夠用數組下

標的方式」[]「引用arguments的元素。arguments.length爲函數實參個數。

function test() {
        var s = "";
        for (var i = 0; i < arguments.length; i++) {
            alert(arguments[i]);
            s += arguments[i] + ",";
        }
        return s;
    }
    test("name", "age")

輸出

name,age

匿名函數中能夠用arguements.callee引用函數自身。

例如 function(){

         if(n>0) return 0;

          else return n+arguments.callee(n+1);

}

 

迴歸正題,咱們能夠用arguments來代替函數中的參數

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你們好! "+this.name+" 我有"+arguments[0]+"張"+arguments[1]+"塊")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];

A.fun.apply(B,monies);    //你們好! 我是小B 我有10張20塊

這裏又有一個問題,可不能夠用Array.prototype.shift.apply(arguments)來代替arguments[0]呢?直接看代碼

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你們好! "+this.name+" 我有"+Array.prototype.shift.apply(arguments)+"張"+arguments[1]+"塊")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];

A.fun.apply(B,monies);    //你們好! 我是小B 我有10張undefined塊

        當咱們使用Array.prototype.shift.apply(arguments)調用以後,arguments[0]就會被抹去,因此arguments[1]就會冒到arguments[0]上。

這能夠看出arguments這個」僞數組「,除了不是」原型繼承自’Array.prototype‘「職位,其餘特徵和數組是同樣的。

 

        最後,咱們考慮一下,若是使用apply方法時,傳入的第一個參數是null時,調用函數時,會發生什麼狀況,會不會報錯呢!

很少說,直接上例子

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你們好! "+this.name+" 我有"+num+"張"+money+"塊")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];
name="我是小C"

A.fun.apply(null,monies);    //你們好! 我是小C 我有10張20塊

能夠看到  若是第一傳入的參數是null的話,在函數提內的this會指向全局對象,在瀏覽器中就是window。

因此能夠總結出兩點:

1.若是函數中有明確使用this,那麼this就會指向傳入的第一個參數的做用域。

2.若是傳入的第一參數爲null時,this就會指向全局的做用域。

 

apply的另外一種用法就是用於將數組分割爲一個個元素。

例如想在數組中a[1,2,3,4]中尋找出最大的袁術出來。

若是直接調用Math.max(a);就會輸出NaN,因此這時候咱們能夠這樣

Math.max.apply(null,a);        //輸出4

 

      聊完了apply以後,咱們再聊一下call就更簡單了,其實他們的做用都是同樣的。他們惟一的區別就是

apply和call在形式參數上的不一樣,apply只能傳入兩個參數且,第二個參數傳入的是數組,而call在

第二參數開始能夠接受任意個參數。你們看下面的例子就一目瞭然了

var A={
    name:"我是小A",
    fun:function(num,money){
        console.log("你們好! "+this.name+" 我有"+num+"張"+money+"塊")
    }
}

var B = {
    name:"我是小B"
}
var monies = [10,20];
A.fun(monies[0],monies[1]);           //你們好! 我是小A 我有10張20塊
A.fun.apply(B,monies);               //你們好! 我是小B 我有10張20塊
A.fun.call(B,monies);                //你們好! 我是小B 我有10,20張undefined塊
A.fun.call(B,monies[1],monies[2]);    //你們好! 我是小B 我有20張undefined塊
相關文章
相關標籤/搜索