技術(shù)頻道導(dǎo)航
HTML/CSS
.NET技術(shù)
IIS技術(shù)
PHP技術(shù)
Js/JQuery
Photoshop
Fireworks
服務(wù)器技術(shù)
操作系統(tǒng)
網(wǎng)站運(yùn)營(yíng)

贊助商

分類目錄

贊助商

最新文章

搜索

JS 面試題:.call 和.apply 有什么區(qū)別?

作者:admin    時(shí)間:2022-7-27 10:4:53    瀏覽:

.apply.call 都是 Function 對(duì)象的方法:Function.apply()、Function.call()。

JavaScript 中的每個(gè)函數(shù)都有許多附加方法,包括toString()call()apply()。請(qǐng)記住, JavaScript 中的每個(gè)函數(shù)都是一個(gè)對(duì)象?,F(xiàn)在我們將關(guān)注函數(shù)的兩個(gè)方法:apply()call()。

call 和.apply 有什么區(qū)別?

call() 方法

讓我們從以下代碼開始:

var x = 10;
 
function f()
{
    console.log(this.x);
}
 
f();

輸出

10

這里我們有一個(gè)名為f() 的全局函數(shù)。f()使用this關(guān)鍵字來(lái)引用x,但請(qǐng)注意我們不會(huì)通過(guò)對(duì)象的實(shí)例調(diào)用該函數(shù)。那么這個(gè)引用的是什么對(duì)象呢?這將引用全局對(duì)象。全局對(duì)象是我們定義變量 x 的地方。上面的代碼確實(shí)有效,并將在對(duì)話框中顯示值 10。

call()apply()都是我們可以用來(lái)在方法調(diào)用期間分配this指針的方法。例如,下面是我們?nèi)绾问褂?code>call()方法:

var x = 10;
var o = { x: 15 };
 
function f()
{
    console.log(this.x);
}
 
f();
f.call(o);

輸出

10
15

f()的第一次調(diào)用將顯示值 10,因?yàn)樗昧巳謱?duì)象。然而,第二次調(diào)用(通過(guò)call方法)將顯示值 1515 是對(duì)象ox屬性的值。call()方法調(diào)用函數(shù)并將其第一個(gè)參數(shù)用作函數(shù)體內(nèi)的this指針。換句話說(shuō) -我們已經(jīng)告訴運(yùn)行時(shí)在函數(shù)f()內(nèi)部執(zhí)行時(shí)引用什么對(duì)象作為this。

我們還可以通過(guò)call()將參數(shù)傳遞給目標(biāo)函數(shù):

var x = 10;
var o = { x: 15 };
function f(message)
{
    console.log(message);
    console.log(this.x);
}
 
f("invoking f");
f.call(o, "invoking f via call");

執(zhí)行結(jié)果

 

apply() 方法

apply()方法與call()相同,只是 apply()需要一個(gè)數(shù)組作為第二個(gè)參數(shù)。該數(shù)組表示目標(biāo)方法的參數(shù)。

var x = 10;
var o = { x: 15 };
function f(message)
{
    console.log(message);
    console.log(this.x);
}
 
f("invoking f");
f.apply(o, ["invoking f through apply"]);

執(zhí)行結(jié)果

apply()方法很有用,因?yàn)槲覀兛梢詷?gòu)建一個(gè)函數(shù),它不關(guān)心目標(biāo)方法的簽名。該函數(shù)可以使用apply()通過(guò)數(shù)組將所有附加參數(shù)傳遞給目標(biāo)方法。

var o = { x: 15 };
 
function f1(message1)
{
    console.log(message1 + this.x);
}
 
function f2(message1, message2)
{
    console.log(message1 + (this.x * this.x) + message2);
}
 
function g(object, func, args)
{
    func.apply(object, args);
}
 
g(o, f1, ["the value of x = "]);
g(o, f2, ["the value of x squared = ", ". Wow!"]);

執(zhí)行結(jié)果

 

參數(shù)標(biāo)識(shí)符

這里的問(wèn)題是笨拙的語(yǔ)法。我們強(qiáng)迫調(diào)用者將參數(shù)填充到一個(gè)數(shù)組中,所以我們調(diào)用apply()。幸運(yùn)的是,有一種方法可以使語(yǔ)法更簡(jiǎn)單,但我們必須再介紹一個(gè)主題:參數(shù)標(biāo)識(shí)符。

在 JavaScript 中,每個(gè)函數(shù)本質(zhì)上都有一個(gè)可變長(zhǎng)度的參數(shù)列表。這意味著即使函數(shù)只使用一個(gè)參數(shù),我們也可以將 5 個(gè)參數(shù)傳遞給函數(shù)。以下運(yùn)行沒(méi)有錯(cuò)誤并顯示“H”:

function f(message)
{
    console.log(message);
}
 
f("H", "e", "l", "l", "o");

輸出

H

如果我們確實(shí)想從f()中訪問(wèn)其他參數(shù),我們可以使用 arguments 關(guān)鍵字。arguments引用了一個(gè) Arguments 對(duì)象,該對(duì)象具有長(zhǎng)度屬性,感覺(jué)就像一個(gè)數(shù)組。

function f(message)
{
    // message param is the same as arguments[0]    
    
    for(var i = 1; i < arguments.length; i++)
    {
        message += arguments[i];
    }
     
    console.log(message); 
}
 
// this will say "Hello"
f("H", "e", "l", "l", "o");

輸出

Hello

正如你所知,arguments 在技術(shù)上不是一個(gè)數(shù)組,即使它像一個(gè)數(shù)組一樣。arguments 具有長(zhǎng)度屬性,但沒(méi)有split、pushpop方法。我們可以對(duì)之前的g()函數(shù)中的參數(shù)做的事情是將參數(shù)[1] 之后的傳入?yún)?shù)復(fù)制到我們傳遞給apply的數(shù)組對(duì)象中。

var o = { x: 15 };
 
function f(message1, message2)
{
    console.log(message1 + (this.x * this.x) + message2);
}
 
function g(object, func)
{           
    // arguments[0] == object
    // arguments[1] == func
     
     
    var args = []; // empty array
    // copy all other arguments we want to "pass through" 
    for(var i = 2; i < arguments.length; i++)
    {
        args.push(arguments[i]);
    }
 
    func.apply(object, args);
}
 
g(o, f, "The value of x squared = ", ". Wow!");

輸出

The value of x squared = 225. Wow!

當(dāng)我們調(diào)用g()時(shí),我們可以將其他參數(shù)作為參數(shù)傳遞,而不是將參數(shù)填充到數(shù)組中。

至此,我們已經(jīng)掌握了理解callapply 所需的理論知識(shí)。

那么.apply 和.call 有什么區(qū)別呢?

解釋它們差異的一個(gè)很好的助記符是:

.call計(jì)算由逗號(hào)分隔的參數(shù)數(shù)量。

.call方法接受一個(gè)或多個(gè)參數(shù)作為對(duì)象,并且需要明確列出,這意味著它是固定數(shù)量的參數(shù)。

foo.call(object, “other argument”, “another one”);

.apply使用數(shù)組作為參數(shù)。

.apply方法需要使用一個(gè)數(shù)組作為其第二個(gè)參數(shù)。如果你不知道要傳遞的參數(shù)數(shù)量或參數(shù)已經(jīng)在數(shù)組中,則使用此方法。

foo.apply(object, [“argument1”, “argument2”, “argument3”]);

從下面程序的注釋了解 .apply 和 .call 的區(qū)別

// .apply 和 .call 如何工作的?

/*
   在這里,我們創(chuàng)建了 2 個(gè)變量,
   x 變量只保存一個(gè)字符串值,
   y 變量包含一個(gè)帶有 x 屬性的對(duì)象,我們稍后將使用 .call 或 .apply 方法訪問(wèn)該對(duì)象
*/
var x = 'hello';
var y = {
  x: 'world' };


// 我們創(chuàng)建一個(gè)標(biāo)準(zhǔn)函數(shù)
function runThis() {
  console.log(this.x);
};

/*
  此調(diào)用將顯示 hello 的值
  因?yàn)槲覀冊(cè)跊](méi)有新實(shí)例的情況下調(diào)用了 runThis 函數(shù)
  runThis 函數(shù)中的“this”關(guān)鍵字將引用全局對(duì)象 x 的值
*/
runThis(); // 顯示 hello

/*
  此調(diào)用將顯示 world 的值
  因?yàn)槲覀兪褂?nbsp;.call 方法調(diào)用了 runThis,
  .call 方法將其第一個(gè)參數(shù)值(y 對(duì)象)用于 runThis 函數(shù)內(nèi)部的 this 關(guān)鍵字
  所以在這里,我們將 y 對(duì)象引用到 'this' 關(guān)鍵字,并且
  我們能夠訪問(wèn)并顯示 x 屬性的值
*/
runThis.call(y); // 顯示 world

// ======================================================================

// 所以 .call 和 .apply 的區(qū)別在哪里?

/*
  在這里,我們創(chuàng)建了一個(gè)名為“a”的變量,其中包含一個(gè)具有“b”屬性的對(duì)象值
*/
var a = {
  b: "foo" };


/*
  我們聲明了一個(gè)接受“msg”參數(shù)的函數(shù),并且
  顯示與 msg 參數(shù)連接的對(duì)象的屬性值
*/
function displayMsg(msg) {
  console.log(this.b + " " + msg);
}

/*
  我們使用 .call 和 .apply 方法調(diào)用了 displayMsg 函數(shù)
  傳入一個(gè)對(duì)象和一個(gè)參數(shù)
*/
displayMsg.call(a, "bar"); // .call 接受一個(gè)或多個(gè)對(duì)象作為它的參數(shù)

displayMsg.apply(a, ["buzz"]); // .apply 需要一個(gè)數(shù)組作為它的參數(shù)

相關(guān)文章

標(biāo)簽: call方法  apply方法  
x
  • 站長(zhǎng)推薦
/* 左側(cè)顯示文章內(nèi)容目錄 */