閑聊js中的apply、call和arguments


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

很少接觸到這兩個方法。但很無奈,很多面試題都要考這兩種方法,我又沒怎么用到,所以我們先來

閑聊下他們到底有什么用和到底怎么用。
         我們先來聊一下apply的用法吧,它是用來改變函數的指向的,說白了,就是指向了別的函數的作用域。

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

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就失去了意義?再來看一下下面的例子

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的指向

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

 

 

      這里聊一下monies,就要說到參數列表,當然我們會想到arguments,在這里插入聊一下arguments。網

上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塊

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM