1. 程式人生 > >閑聊js中的apply、call和arguments

閑聊js中的apply、call和arguments

fin 不同 對象實例 意義 his 引用 最大的 調用 函數

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張20塊

當我們使用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塊

閑聊js中的apply、call和arguments