3

鉴于:

function shout(){ alert('Hello!'); }
var dasarray = [ shout ];

shout();
dasarray[0]();

shout = function(){ alert('World!'); }

shout();
dasarray[0]();

输出:

Hello!

Hello!

World!

Hello!

我原以为会dasarray收到对该函数的引用shout,但遗憾的是第四个输出也是hello。如果我假设正确,我能够shout正确修改函数,但这导致我假设函数没有通过引用传递到dasarray.

我已经用一个对象尝试了这个例子,而不是一个数组:

dasarray = { myfunction: shout }

同样令人失望的结果。

我的意图是有一个数组/对象/具有按顺序运行并且可以实时扩展的函数。

例如,使用新功能扩展 JavaScript 代码并向以正确顺序运行的现有事件添加额外的函数调用。

那么,如何通过引用将函数放入数组/对象中?


谢谢你的好答案。我只是想解释一下我选择了Eli 的答案,因为它引导我进入这个设置:

zzz = {
    calls: [],
    shout: function(message) {
        alert('Shouting: ' + message);
    },
    initialize: function () {
        zzz.calls.push(['shout','Hello World']);
        zzz.calls.push(['shout','this is']);
        zzz.calls.push(['shout','my last shout!']);
        zzz.run();

        zzz.shout = function(){ alert('modified!'); };
        zzz.run();
    },
    run: function () {
        $.each(zzz.calls, function(){ zzz[this[0]](this[1]); }); // <- Using jQuery $.each here, just to keep it easy
    }
};

zzz.initialize();
4

2 回答 2

7

我原以为 dasarray 收到了对该函数的引用shout

确实如此。它没有收到对变量 shout的引用。(在函数声明中由函数名称定义的符号实际上是一个变量——这就是为什么你可以稍后分配给它的原因。)所以你后面的行改变了这个变量:

shout = function(){ alert('World!'); }

...对 . 中早期函数的引用没有影响dasarray

将对象引用视为一个值,说明在哪里可以找到对象。当你这样做时:

function shout(){ alert('Hello!'); }

...符号shout接收一个,说明该函数的位置,如下所示:

指向函数对象的变量喊

那么当你这样做时:

var dasarray = [ shout ];

...该放在数组的第一个条目中。现在符号shout和第一个条目dasarray都具有相同的值,这告诉 JavaScript 引擎在内存中的哪里可以找到该函数对象。所以我们有这个:

指向同一个函数对象的变量喊和 dasarray 条目 0

但是变量shout和 in 之间的条目dasarray没有任何联系。

然后你这样做:

shout = function(){ alert('World!'); }

...创建一个新函数并将一个新值存储在变量shout中,说明该新函数在哪里。dasarray但这对存储在's 条目中的值没有影响0。我们最终得到了这个:

var 喊指向第二个函数,dasarray 条目 0 指向第一个函数

我在上面说了很多“值”,因为这就是“对象引用”的含义:一个值,就像值一样5。只是 value 的使用方式是查找对象的位置。当您将该值从一个变量分配给另一个变量时,该值将被复制,就像您将值从一个变量复制5到另一个变量时一样。

我不能说我很喜欢Eli 的解决方法,我宁愿对它更直接,并以简单的方式使用对象:

var obj = {
    shout: function() { alert("Hello!"); }
};
var dasarray = [ obj ];

obj.shout();                               // Hello!
dasarray[0].shout();                       // Hello!

obj.shout = function() { alert("World"); };

obj.shout();                               // World!
dasarray[0].shout();                       // World!
于 2013-03-15T17:29:10.023 回答
3

我同意TJ 的回答。但是,如果您想做某种解决方法,您可以创建一个始终从函数缓存中进行“及时”查找的函数。看到这个小提琴

var getFunctionRef = function(funcName)
{
    return function() { global[funcName](); };
}

var global = { };
var arr = [];

global.shout = function() { alert('hello'); }

arr[0] = getFunctionRef('shout');

global.shout = function() { alert('world'); }

arr[0]();

这是一个非常基本的例子。有更广泛的方法来做到这一点。但这应该证明这个概念。

于 2013-03-15T17:34:09.723 回答