Javascript 哪种方法更好:function.apply(<;this>;,args)或使用函数接受<;这>;作为论据?

Javascript 哪种方法更好:function.apply(<;this>;,args)或使用函数接受<;这>;作为论据?,javascript,Javascript,假设我有一个定义如下的函数: functionA = function(myObject, someParams) { myObject.save_some_data = someParams; myObject.processed = true; } 然后我可以调用它并将一个对象作为function(someObject,someParams)传递给它 但是,我可以使用apply()转换此示例: 这两种方法似乎达到了相同的目标,还是我遗漏了什么 但是,既然JavaScript中确实存

假设我有一个定义如下的函数:

functionA = function(myObject, someParams) {
  myObject.save_some_data = someParams;
  myObject.processed = true;
}
然后我可以调用它并将一个对象作为
function(someObject,someParams)
传递给它

但是,我可以使用
apply()
转换此示例:

这两种方法似乎达到了相同的目标,还是我遗漏了什么


但是,既然JavaScript中确实存在
apply()
,使用它而不是让我的函数将
this
作为第一个参数有什么好处?

apply
将使用
someParams
作为一个参数数组<代码>调用实际上会做同样的事情:

functionA.call(someObject, someParams);

除了风格之外,没有其他好处。在大多数情况下,将
someObject
作为参数传递可能更有意义,但这实际上取决于您以及您最喜欢哪一个。

当您需要在另一个对象B的上下文中调用某个对象A的现有方法时(好像它是在另一个对象B上定义的),调用/应用非常有用

例如:

var john={
姓名:“约翰·多伊”,
first_name:function(){返回this.name.split(“”)[0]}
}
var jane={
姓名:“简·多伊”,
}
john.first\u name.call(jane)//重用来自john的方法
//好像是为简定义的
//(将返回“Jane”)
[更新]

当然,这只是一个人工的例子来说明这个想法,但是调用/应用方法有很多合理的应用。以下只是几个例子:

1.简化客户端代码 假设您要将方法
fname
添加到对象
jane={name:'jane Doe'}
,该方法应允许您执行以下操作:

jane.fname(function(){返回this.name[0]})/=>J
jane.fname(function(){返回this.name.split(“”)[1]})/=>Doe
您可以尝试以下方法之一:

/(1)天真(错误!)的方法:
jane.fname=函数(回调){return callback()}
//问题:回调函数不知道'this`==jane
jane.fname(函数(){return this.name})/=>未定义
//(2)直截了当的方法:
jane.fname=函数(回调){返回回调(this)}
fname(函数(self){return self.name})/=>janedoe
//(3)调用/应用方法
jane.fname=函数(回调){return callback.call(this)}
jane.fname(函数(){return this.name})/=>jane Doe
可以看出,直截了当的方法(2)和调用/应用(3)都可以按预期工作,但最新的方法针对“外部”使用进行了优化,这在库中非常有用(想想jQuery)

2.传递数组而不是参数列表 另一个例子。我们有一系列数字:

var数=[5,6,2,3,7];
我们想找到其中最大的一个。现在,我们有一个Math.max函数,但是我们不能很容易地使用它,因为它不接受任意的数字数组:
Math.max(5,6)
Math.max(5,6,2,…)
是可能的,但是
Math.max(数字)
不是。幸运的是,我们可以使用apply绕过此约束:

Math.max.apply(空,数字);
//在这种情况下,我们可以使用任何对象而不是null,
//因为Math.max不依赖于此对象的
如您所见,我们可以使用
apply
将数组有效地转换为参数列表。(但要小心使用大型数组:有超过JavaScript引擎参数长度限制的风险;更多详细信息)

3.构造函数链接 这可能是一个最重要的用例:

// constructor for a NamedEntity "class":
function NamedEntity(name) {
  this.name = name;
}

function Person(first_name, last_name) {
  this.last_name = last_name;
  // reuse NamedEntity's constructor:
  NamedEntity.call(this, first_name + ' ' + last_name);
}

var john = new Person('John', 'Doe')
john.name // => John Doe


值得一提的是,从ECMAScript 5开始,还有一个
bind
函数,在语义上与
call
apply
相关,这让我们甚至可以做对不起,当然我指的是一些参数的数组。我将编辑我的问题。所以,使用
apply()/call()
的唯一原因是风格?@mishik:不总是,但如果你可以选择在哪里使用它以及如何编写它,那么是的,我可以这么说。
call
apply
是在对象上使用不同于其本机对象类型的方法所必需的。如果没有必要,我永远不会使用
apply
。如果你还对这个问题感兴趣的话,我刚刚用几个更实际的例子更新了我的答案。另一个场景是在不是数组实例的对象上使用数组实例方法,但它们的行为与数组实例类似。例如,节点列表可以像数组一样编制索引,并且具有length属性,但没有数组实例的方法。我们仍然可以通过调用在节点列表上使用这些数组实例方法:
Array.prototype.slice.call(节点列表,0,10);//仅选择前10个节点
。在
参数
对象上使用数组实例方法是另一种情况。
// constructor for a NamedEntity "class":
function NamedEntity(name) {
  this.name = name;
}

function Person(first_name, last_name) {
  this.last_name = last_name;
  // reuse NamedEntity's constructor:
  NamedEntity.call(this, first_name + ' ' + last_name);
}

var john = new Person('John', 'Doe')
john.name // => John Doe