2009-06-27 34 views
1

我可能最好通過代碼解釋這一點。我有這樣的事情:一個棘手的JavaScript問題

var object1 = function(){ 
    //do something 
} 
var object2 = function(){ 
    //do something else 
} 

var objects = { 
    'o1' : object1, 
    'o2' : object2 
}; 

var actions = []; 

function addAction(actionName){ 
var object = objects[actionName]; 
actions.push(function(){ new object(); }); 
} 

所以這個代碼,節省了根據用戶的輸入被保存在一個陣列運行時確定的一系列動作。

addAction("o1"); 
addAction("o2"); 

如果我想重播序列我只是做:

for(i in actions){ 
    actions[i](); 
} 

,這將創建一個類型object1和對象2的兩個匿名對象。

現在,我需要以某種方式序列化動作[]數組,但我需要其中的每個函數來保留它的範圍。如果我只是投的功能爲字符串,我得到:

"function(){ new object(); }" 

,如果我EVAL這個字符串,然後「對象」將是不確定的。你會如何做到這一點?

回答

1

我有點不清楚你希望函數有什麼範圍。

只需按下功能

actions.push(objects[actionName]); 

可能有你想要的效果...

5

爲什麼不能在一個對象與函數一起保持動作的名稱,這樣就可以使用對於系列化:

function Action(name, func) { 
    this.name = name; 
    this.func = objects[name]; 
} 

function addAction(actionName) { 
    actions.push(new Action(actionName)); 
} 

運行功能會稍微改變代碼:

for (i in actions) actions[i].func(); 

爲了連載陣列你只需把名字中的字符串:

var s = ''; 
for (i in actions) { 
    s += (s.length == 0 ? '' : ',') + actions[i].name; 
} 

然後deserialise您剛剛從名稱重新創建對象:

var names = s.split(','); 
for (i in names) { 
    addAction(new Action(names[i])); 
} 
2

如果你想序列您稍後回放的動作列表,您應該修改您的addAction函數以存儲動作的名稱。

function addAction(actionName) 
{ 
    actions.push(actionName); 
} 

而當你去回放,你會使用

for(i in actions) 
{ 
    objects[actions[i]](); 
} 

因爲你的行動清單僅僅是字符串,你應該有序列化沒有問題。