对象的Javascript函数作为参数

时间:2013-11-16 15:33:06

标签: javascript this

假设我们有一个定义为

的对象

var object = {counter: 0; increment: function() { this.counter++; } };

现在,调用对象的递增函数将按预期增加计数器。

object.increment(); //object.counter will now equal to 1

我的错误是我会有一个调用参数函数的函数,计数器不会递增,因为this变量指向调用函数的闭包。

function call(func) { func(); }; call(object.increment); //object.counter still 1

所以我的问题是,是否有任何方法可以使调用函数保持此变量不变,以便在调用时增加object.counter的效果?

编辑: 由于更深入的解释,改变了已接受的答案。

2 个答案:

答案 0 :(得分:3)

考虑它的一种方法是JavaScript中的this关键字定义的对象的引用,但引用当前的调用者 - 正在进行调用的对象。考虑一下你的例子:

var counter = {counter: 0; increment: function() { this.counter++; } };

如果我们要构建另一个具有相似形式的对象,我们可以“借用”increment函数:

var startAt100 = {counter:100, increment: counter.increment }
startAt100.increment()
// startAt100.counter == 101

这里,因为startAt100对象正在进行调用,所以函数this内部引用startAt100

解决此问题的一种方法是使用bind()功能。 bind()函数接受一个函数并返回该函数的一个版本,其中this始终指向同一个调用者。

  

注意:bind()还能够执行函数参数的部分应用程序,这也很有用。

因此,我们可以通过执行以下操作来创建增量的绑定函数:

var boundIncrement = counter.increment.bind(counter);

现在,当我们调用boundIncrement()时 - 无论实际调用者是谁 - 函数内的this都会指向counter对象。

boundIncrement() // counter.counter == 1
call(boundIncrement) // counter.counter == 2

了解bind()

为了更详细地理解bind(),我们可以纯粹在javascript中实现一个绑定函数。它看起来像这样:

function bind(fn, invoker) {
  return function() {
    return fn.apply(invoker, arguments);
  }
}

Binding返回一个函数,该函数将在特定的上下文中调用提供的fn,并始终在该上下文中。

  

注意:一旦函数绑定到上下文/调用者,您就无法“撤消”该绑定。在绑定函数上使用.call().apply()不会更改this

另一种方法:对象构造

另一种方法是改变构建counter对象的方式。我们可以使用匿名函数来创建一个稳定的作用域,然后创建一个引用该作用域中的变量的闭包。通过这样做,您可以创建一个具有稳定执行环境的函数,而不是使用this。请考虑以下代码:

var counter = (function() {
  var state = { counter: 0 }
  state.increment = function() { state.counter += 1; };
  return state;
})();

counter.increment() // counter.counter == 1
call(counter.increment); // counter.counter == 2

现在,当您调用counter.increment()时,由于state已经创建了函数,因此将始终指向并变异该特定对象。

这不是更好或更糟,只是一种不同的方式来理解函数如何在JavaScript中工作的相同基础概念。

答案 1 :(得分:1)

您可以使用.bind()

  call(object.increment.bind(object));

如果您必须支持没有.bind()的旧运行时环境,您可以将其包装在函数中:

  call(function() { object.increment(); });