假设我有一个如下定义的functionA:
functionA = function(myObject, someParams) {
myObject.save_some_data = someParams;
myObject.processed = true;
}
然后我可以调用它并将对象传递给functionA(someObject, someParams)
。
但是,我可以使用apply()
:
functionA = function(someParams) {
this.save_some_data = someParams;
this.processed = true;
}
functionA.apply(someObject, [someParams]);
这两种方法似乎都达到了同样的目标,或者我错过了什么?
但是,由于JavaScript中存在apply()
,使用它而不是让我的函数接受this
作为第一个参数有什么好处?
答案 0 :(得分:3)
apply
将使用someParams
作为参数数组; call
实际上会做同样的事情:
functionA.call(someObject, someParams);
除了款式,没有任何好处。在大多数情况下,传递someObject
作为参数可能会更有意义,但这取决于你和你最喜欢哪一个。
答案 1 :(得分:2)
当您需要在另一个对象B的上下文中调用某个对象A的现有方法时,调用/应用非常有用。
例如:
var john = {
name: 'John Doe',
first_name: function() { return this.name.split(' ')[0] }
}
var jane = {
name: 'Jane Doe',
}
john.first_name.call(jane) // reuse method from john
// as if it was defined for jane
// (will return 'Jane')
[UPDATE]
当然,这只是一个人为的例子来说明这个想法,但是有很多合理的应用程序用于调用/应用方法。以下是几个例子:
想象一下,您想要将方法fname
添加到对象jane = {name: 'Jane Doe'}
,以便您执行以下操作:
jane.fname(function() { return this.name[0] }) // => J
jane.fname(function() { return this.name.split(' ')[1] }) // => Doe
您可以尝试以下方法之一:
// (1) naive (wrong!) approach:
jane.fname = function(callback) { return callback() }
// problem: the callback function won't know that `this` == jane
jane.fname(function() { return this.name }) // => undefined
// (2) straightforward approach:
jane.fname = function(callback) { return callback(this) }
jane.fname(function(self) { return self.name }) // => Jane Doe
// (3) call / apply approach
jane.fname = function(callback) { return callback.call(this) }
jane.fname(function() { return this.name }) // => Jane Doe
可以看出,直接(2)和call / apply(3)方法都按预期工作,但最新的方法针对“外部”使用进行了优化,这在库中非常有用(想想jQuery) )
另一个例子。我们有一系列数字:
var numbers = [5, 6, 2, 3, 7];
我们希望找到其中最大的一个。现在,我们有一个Math.max函数,但我们不能轻易使用它,因为它不接受任意数组:Math.max(5, 6)
和Math.max(5, 6, 2, ...)
是可能的,但是{{1} } 不是。幸运的是,我们可以使用apply来绕过这个约束:
Math.max(numbers)
如您所见,我们可以使用Math.max.apply(null, numbers);
// we could use any object instead of null in this case,
// because Math.max doesn't depend on the this object
将数组有效地转换为参数列表。 (但要注意大型数组:存在超出JavaScript引擎的参数长度限制的风险;更多细节here)
这可能是一个最重要的用例:
apply
值得一提的是,从ECMAScript 5开始,还有一个// 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
函数,在语义上与bind
和call
相关,这让我们做more interesting things