3

环顾四周后,我找不到这个问题的答案,尽管我怀疑以前有人问过这个问题。我能找到的最接近的是对象中的这个函数指针,尽管它并没有得到我想要的。

假设我们有这样一段代码:

var foo = function () { /* some code */ };

现在,我假设在评估期间名称 foo 在其环境中绑定到函数的内部表示,然后在应用程序期间查找。

现在假设我们在程序的稍后部分有一个对象:

var obj = {};
obj.func = foo;

此时,环境中应该有同一个函数对象的两个副本,一个绑定到 foo,另一个绑定到 obj.func。但是假设我不想要该函数的两个副本,而是让 obj.func 指向 foo——有没有办法做到这一点?这就是我想出的:

var obj = {};
obj.func = function () { foo(); };

这行得通吗?有没有更好的办法?

非常感谢

编辑澄清

抱歉——我认为我说得不够清楚。我希望这有帮助。

我不确定 Javascript 评估过程是如何工作的,但假设它跟踪一些内部表示的环境,我们将在这里抽象地表示为一组键值对。

现在,当评估者看到一些代码时,例如

var foo = function () { /* some code  */ };

它在它的环境中构造它:['foo' : [function object]]。然后,稍后,当它看到这样的东西时:

var bar = foo;

它在环境中查找 foo 以检索它的值,一个函数对象,然后像这样扩充环境。['foo':[函数对象],'bar':[函数对象]]。现在,相同的功能在环境中确实存在两次。这是javascript设置环境的方式吗?如果没有,那么它是如何做到的?

我问的动机如下。假设我们定义了一些函数,然后我们导出一个对象作为这些函数的接口,并且我们知道我们将要实例化很多次。如果对象包含指向函数的指针,而不是函数本身,则效率会更高。

4

5 回答 5

6

JS变量、对象属性等不直接持有对象;它们持有对对象的引用。当你说var foo = function() { };,foo被分配一个对你刚刚定义的函数的引用。(顺便说一下,不是指针。区别可能很微妙,但很重要。JS 没有用户可见的指针,所以这不是什么大问题。但是这样做的语言使用它们的方式不同。不要让自己以后必须忘掉东西。)

稍后在程序中,当您说 时obj.func = foo;,您将引用复制到obj.func. 不是函数——仍然只有一个函数对象,有两个对它的引用。

所以obj.func = foo;已经做到了你所说的。当您调用 时obj.func(),它实际上调用的是由 . 引用的完全相同的函数foo。但是,有一个巨大的区别,这可能是给您带来麻烦的原因: obj.func是“方法调用”,而 JS 设置thisobj函数内部。如果foo用于this任何东西,假设它是其他对象,它会感到失望。

如果这是一个问题,你可能会做类似的事情

var that = this;
var foo = function() { /* use `that` instead of `this` here */ };

然后,无论你调用函数为fooor obj.func,它都不受更改的影响this

如果这没有帮助,您需要澄清问题。

于 2012-08-07T03:58:59.263 回答
0

您是否尝试过运行您的示例?

是的,这确实有效,但是请注意,如果您更改foo变量,它也会更改objc.func(). 我不知道有其他方法可以做到这一点。

于 2012-08-07T03:57:59.213 回答
0

这不是真的:

此时,环境中应该有同一个函数对象的两个副本,一个绑定到 foo,另一个绑定到 obj.func。但是假设我不想要该函数的两个副本,而是让 obj.func 指向 foo

如果你以这种方式分配东西,那么 obj.func 和 foo 指向同一个东西。我什至认为不可能复制一个函数。

于 2012-08-07T03:58:27.923 回答
0

稍微详细说明一下:

函数是 javascript 中的一等公民或对象。它们的使用与任何其他对象一样。

var foo = func() {
//some code
};

类似于

var foo = {
//some code
};

在 Javascript 中,所有对象都是通过引用传递的。据我所知,javascript对象没有指针或按值传递的概念。

因此,当您将两个引用分配给同一个函数时,不会复制该函数对象。但是,对于两个引用,函数的内部状态保持不变。在你的情况下 foo 和 obj.func()

于 2012-08-07T07:09:16.567 回答
-1

此时,环境中应该有同一个函数对象的两个副本,一个绑定到 foo,另一个绑定到 obj.func。

你这么认为?只是出于好奇,如果代码说:

var obj = {};
obj.func = 5;

有多少副本在5四处飘荡?

不会。所有代码都被转换为函数,这些函数本质上是常量。您可以毫无困难地将多个变量分配给同一个常量。

至于“绑定”,绑定发生在函数被调用的时候。也就是this参数设置为obj,嗖嗖嗖……

于 2012-08-07T03:58:09.617 回答