【问题标题】:Javascript: Putting Function Pointers in an Object?Javascript:将函数指针放入对象中?
【发布时间】:2012-08-04 01:20:47
【问题描述】:

环顾四周后,我找不到这个问题的答案,尽管我怀疑以前有人问过这个问题。我能找到的最接近的是Function pointers in objects,尽管它并没有完全符合我的要求。

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

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设置环境的方式吗?如果没有,那它是怎么做到的?

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

【问题讨论】:

  • 你说的这些“函数指针”是什么? JS 甚至没有 指针。
  • 你能给出一些动力来说明你到底想要做什么需要这个吗?

标签: javascript node.js pointers scope function-pointers


【解决方案1】:

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

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

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

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

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

那么,无论你调用函数为foo还是obj.func,它都不受this变化的影响。

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

【讨论】:

  • 是的!某种代理...谢谢! ;-)
【解决方案2】:

稍微详细说明一下:

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

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

类似于

var foo = {
//some code
};

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

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

【讨论】:

    【解决方案3】:

    这不是真的:

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

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

    【讨论】:

    • 这在一定程度上可能是可能的,但不是偶然的——也不是完美的。它需要意图和邪恶。 var copy = eval("("+foo+")"); 应该半做。当然,这不会保留到由foo 关闭的任何变量的链接,因此该函数很可能最终无用。
    【解决方案4】:

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

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

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

    5 的副本有多少?

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

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • Nitpick:如果您修改 foo 引用的对象,它也会更改obj.func 引用的对象——因为它们是同一个对象。但是如果你改变变量——也就是说,如果你说foo = anything_else;obj.func将不受影响。
      猜你喜欢
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多