技术频道导航
HTML/CSS
.NET技术
IIS技术
PHP技术
Js/JQuery
Photoshop
Fireworks
服务器技术
操作系统
网站运营

赞助商

分类目录

赞助商

最新文章

搜索

JS 面试题:.call 和.apply 有什么区别?

作者:admin    时间:2022-7-27 10:4:53    浏览:

.apply.call 都是 Function 对象的方法:Function.apply()Function.call()

JavaScript 中的每个函数都有许多附加方法,包括toString()call()apply()。请记住, JavaScript 中的每个函数都是一个对象。现在我们将关注函数的两个方法:apply()call()

call 和.apply 有什么区别?

call() 方法

让我们从以下代码开始:

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

输出

10

这里我们有一个名为f() 的全局函数。f()使用this关键字来引用x,但请注意我们不会通过对象的实例调用该函数。那么这个引用的是什么对象呢?这将引用全局对象。全局对象是我们定义变量 x 的地方。上面的代码确实有效,并将在对话框中显示值 10

call()apply()都是我们可以用来在方法调用期间分配this指针的方法。例如,下面是我们如何使用call()方法:

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

输出

10
15

f()的第一次调用将显示值 10,因为它引用了全局对象。然而,第二次调用(通过call方法)将显示值 1515 是对象ox属性的值。call()方法调用函数并将其第一个参数用作函数体内的this指针。换句话说 -我们已经告诉运行时在函数f()内部执行时引用什么对象作为this

我们还可以通过call()将参数传递给目标函数:

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");

执行结果

 

apply() 方法

apply()方法与call()相同,只是 apply()需要一个数组作为第二个参数。该数组表示目标方法的参数。

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"]);

执行结果

apply()方法很有用,因为我们可以构建一个函数,它不关心目标方法的签名。该函数可以使用apply()通过数组将所有附加参数传递给目标方法。

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!"]);

执行结果

 

参数标识符

这里的问题是笨拙的语法。我们强迫调用者将参数填充到一个数组中,所以我们调用apply()。幸运的是,有一种方法可以使语法更简单,但我们必须再介绍一个主题:参数标识符

在 JavaScript 中,每个函数本质上都有一个可变长度的参数列表。这意味着即使函数只使用一个参数,我们也可以将 5 个参数传递给函数。以下运行没有错误并显示“H”:

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

输出

H

如果我们确实想从f()中访问其他参数,我们可以使用 arguments 关键字。arguments引用了一个 Arguments 对象,该对象具有长度属性,感觉就像一个数组。

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 在技术上不是一个数组,即使它像一个数组一样。arguments 具有长度属性,但没有splitpushpop方法。我们可以对之前的g()函数中的参数做的事情是将参数[1] 之后的传入参数复制到我们传递给apply的数组对象中。

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!

当我们调用g()时,我们可以将其他参数作为参数传递,而不是将参数填充到数组中。

至此,我们已经掌握了理解callapply 所需的理论知识。

那么.apply 和.call 有什么区别呢?

解释它们差异的一个很好的助记符是:

.call计算由逗号分隔的参数数量。

.call方法接受一个或多个参数作为对象,并且需要明确列出,这意味着它是固定数量的参数。

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

.apply使用数组作为参数。

.apply方法需要使用一个数组作为其第二个参数。如果你不知道要传递的参数数量或参数已经在数组中,则使用此方法。

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

从下面程序的注释了解 .apply 和 .call 的区别

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

/*
   在这里,我们创建了 2 个变量,
   x 变量只保存一个字符串值,
   y 变量包含一个带有 x 属性的对象,我们稍后将使用 .call 或 .apply 方法访问该对象
*/
var x = 'hello';
var y = {
  x: 'world' };


// 我们创建一个标准函数
function runThis() {
  console.log(this.x);
};

/*
  此调用将显示 hello 的值
  因为我们在没有新实例的情况下调用了 runThis 函数
  runThis 函数中的“this”关键字将引用全局对象 x 的值
*/
runThis(); // 显示 hello

/*
  此调用将显示 world 的值
  因为我们使用 .call 方法调用了 runThis,
  .call 方法将其第一个参数值(y 对象)用于 runThis 函数内部的 this 关键字
  所以在这里,我们将 y 对象引用到 'this' 关键字,并且
  我们能够访问并显示 x 属性的值
*/
runThis.call(y); // 显示 world

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

// 所以 .call 和 .apply 的区别在哪里?

/*
  在这里,我们创建了一个名为“a”的变量,其中包含一个具有“b”属性的对象值
*/
var a = {
  b: "foo" };


/*
  我们声明了一个接受“msg”参数的函数,并且
  显示与 msg 参数连接的对象的属性值
*/
function displayMsg(msg) {
  console.log(this.b + " " + msg);
}

/*
  我们使用 .call 和 .apply 方法调用了 displayMsg 函数
  传入一个对象和一个参数
*/
displayMsg.call(a, "bar"); // .call 接受一个或多个对象作为它的参数

displayMsg.apply(a, ["buzz"]); // .apply 需要一个数组作为它的参数

相关文章

标签: call方法  apply方法  
x
  • 站长推荐
/* 左侧显示文章内容目录 */