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

贊助商

分類目錄

贊助商

最新文章

搜索

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

作者:admin    時間:2022-7-27 10:4:53    瀏覽:

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

JavaScript 中的每個函數(shù)都有許多附加方法,包括toString()、call()apply()。請記住, JavaScript 中的每個函數(shù)都是一個對象。現(xiàn)在我們將關注函數(shù)的兩個方法:apply()call()。

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

call() 方法

讓我們從以下代碼開始:

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

輸出

10

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

call()apply()都是我們可以用來在方法調(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,因為它引用了全局對象。然而,第二次調(diào)用(通過call方法)將顯示值 1515 是對象ox屬性的值。call()方法調(diào)用函數(shù)并將其第一個參數(shù)用作函數(shù)體內(nèi)的this指針。換句話說 -我們已經(jīng)告訴運行時在函數(shù)f()內(nèi)部執(zhí)行時引用什么對象作為this。

我們還可以通過call()將參數(shù)傳遞給目標函數(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()需要一個數(shù)組作為第二個參數(shù)。該數(shù)組表示目標方法的參數(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()方法很有用,因為我們可以構(gòu)建一個函數(shù),它不關心目標方法的簽名。該函數(shù)可以使用apply()通過數(shù)組將所有附加參數(shù)傳遞給目標方法。

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ù)標識符

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

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

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

輸出

H

如果我們確實想從f()中訪問其他參數(shù),我們可以使用 arguments 關鍵字。arguments引用了一個 Arguments 對象,該對象具有長度屬性,感覺就像一個數(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ù)組,即使它像一個數(shù)組一樣。arguments 具有長度屬性,但沒有split、pushpop方法。我們可以對之前的g()函數(shù)中的參數(shù)做的事情是將參數(shù)[1] 之后的傳入?yún)?shù)復制到我們傳遞給apply的數(shù)組對象中。

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!

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

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

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

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

.call計算由逗號分隔的參數(shù)數(shù)量。

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

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

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

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

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

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

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

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


// 我們創(chuàng)建一個標準函數(shù)
function runThis() {
  console.log(this.x);
};

/*
  此調(diào)用將顯示 hello 的值
  因為我們在沒有新實例的情況下調(diào)用了 runThis 函數(shù)
  runThis 函數(shù)中的“this”關鍵字將引用全局對象 x 的值
*/
runThis(); // 顯示 hello

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

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

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

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


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

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

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

相關文章

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