2013-03-15 82 views
3

鉴于:Javascript数组/对象通过引用

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

shout(); 
dasarray[0](); 

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

shout(); 
dasarray[0](); 

输出:

Hello! 

Hello! 

World! 

Hello! 

我已经预期dasarray接收到功能shout的引用,但遗憾的是该第四输出是也是你好。如果我假设是正确的,我可以正确修改shout函数,但是这导致我认为函数没有通过引用传递给dasarray

相反的阵列我已经尝试过与对象本实施例的:

dasarray = { myfunction: shout } 

在相同的,令人失望的,结果。

我的意图是拥有一个/有功能的数组/对象,它们按顺序运行并且可以实时扩展。 例如,用新功能扩展javascript,并向现有事件添加其他函数调用,这些调用以正确的顺序运行。

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


编辑:谢谢你的好答案。我只是想说明,我选择以利的答案,因为它使我这个设置:

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(); 
+0

它是对函数的引用。你正在改变'shout'指向什么,数组仍然引用相同的函数。 – Shmiddty 2013-03-15 17:31:14

回答

3

我同意T.J.的答案。但是,如果您想要采取某种解决方法,则可以创建一个函数,该函数始终会对函数缓存执行“及时”查找。看到这fiddle

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](); 

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

+0

谢谢Eli,TJ以一种非常好的方式解释了为什么这不是一个比通过价值传递更有价值的参考,但是您的解决方案也将我推向了正确的方向解决我的问题! – FTav 2013-03-15 18:04:39

7

我会一直期待dasarray接收功能shout

它做参考。它确实是而不是收到变量的参考shout。 (函数声明中函数名称所定义的符号实际上是所有意图和目的的变量  —这就是为什么您可以稍后分配它的原因。)所以您的后面的行变化该变量:

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

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

将对象引用看作是指示在何处查找对象的值。当你这样做:

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

...符号shout收到说,其中该功能被发现,像这样:

Variable <code>shout</code> pointing to function object

然后,当你这样做:

var dasarray = [ shout ]; 

...即放入第一个条目在数组中。现在符号shoutdasarray中的第一个条目都具有相同的值,它告诉JavaScript引擎在内存中何处找到该函数对象。因此,我们有这样的:

Variable <code>shout</code> and <code>dasarray</code> entry 0 pointing to same function object

但变量shoutdasarray进入任何有彼此没有联系。

然后你这样做:

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

...创建一个新的功能,并存储在变量shout说,其中新功能是一种新的价值。但是这对存储在dasarray的条目0中的值没有影响。我们结束了这一点:

Var <code>shout</code> pointing to second function, <code>dasarray</code> entry 0 pointing to first function

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

我不能说我喜欢利的解决办法了,我宁愿只是更加直接的了解,并在简单的方式使用对象:

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! 
+0

感谢您的回答,这很清楚,但@EliGassert还提供了一个非常好的解决方法:) – FTav 2013-03-15 18:03:29

+0

@FTav:很高兴帮助。对Eli应有的尊重,但我认为有更好的方式来做到这一点。这比需要更复杂。 FWIW,我已经给出了更直接的方式。 – 2013-03-15 18:13:26

+0

没有关于您的解决方案的疑虑。它很干净(特别是新的编辑)。 +1给你的答案。我的解决方案非常通用,不适用于真实世界的场景。我想象了另一个或两个抽象概念,将dasarray从调用者中分离出来。否则,你甚至可以更直接地将'global'改为'dasarray',并直接修改数组中的函数。但我认为真实的解决方案比我们提供的示例和解决方案更复杂。 – 2013-03-15 18:24:21