2011-08-08 45 views
2

我正在制作一个使用上下文菜单作为其主UI的Google Chrome扩展程序。每个菜单项都会触发相同的内容脚本,但具有不同的参数。我主要做的每一个项目(及其相应的数据)存储在具有下列形式的JSON对象的形式:JavaScript数组将无法正常填充

{name, parent_id, rule_number, meta_array[], childCount} 

名,CHILD_COUNT和PARENT_ID用于创建等级时,则上下文菜单建成。传递给脚本的数据是rule_number(int)和meta_array(字符串数组)。所有这些对象都存储在一个名为indexData []的数组中。

当单击一个菜单项时,提供的id仅用作“indexData”数组中的索引以获取正确的数据并将其传递给脚本。

例如:

// Iterates through the objects 
for(var j = 0; j < objectsArray.length; j++) { 

// Context menu created with unique id 
var id = chrome.contextMenus.create({ 
"title": objectArray[j].name, 
"onclick": injectScript, 
"parentId": objectsArray[j].parent_id }); 

// Stores the objects at the corresponding index 
indexData[id] = objectsArray[j]; } 

现在,有一个特别大的数据集是回来频繁。每次我希望将它们作为菜单的一部分时,不要每次列出这些元素中的每一个,而只是将每个需要此组数据的JSON对象添加为其子元素。当创建菜单时,如果此布尔值设置为true,则会调用一个函数。然后该脚本只是遍历一个单独的对象列表,并使它们成为这个父对象的子对象。创建的孩子甚至从父对象继承某些东西。例如,如果父对象具有这样的[“1”,“2”,“3”,“4”]这样的meta_array,则其子女可能看起来都像[“1”,“2”,“ custom_children_data [3],“4”]。

问题是这最后一部分不起作用。虽然孩子们创建得很好并且名称正确,但与他们相关的数据是错误的。它始终是该单独列表中最后一个对象的数据。这是函数的样子:

// Iterate through children list 
for(var i = 0; i < separateList.length; i++){ 

// Just copying the passed parent object's data 
var parentData = data; 

var id = chrome.contextMenus.create({ 
"title": separateList[i].name, // Get item [i] of the children list (works fine) 
"onclick": injectScript, 
"parentId": parentId   // Will become a child of parent object 
}); 


// Trying to change some data, this is where things go wrong. 
parentData.meta[2] = separateList[i].meta; 

// Save in indexData 
indexData[id] = parentData; } 

在循环的第一次迭代,parentData.meta [2]获取列表中的权值,然后该值被保存在indexdata。但在随后的迭代中,indexData中已经存在的所有值只会被刷新并被从列表中读取的最新数据替换。当读取最后一个值时,indexData中所有新添加的元素都会更改为最后一个值,这就解释了我的问题。但为什么它会这样做呢?在某些情况下,Java是通过地址而不是数值来处理数组呢?

也许我错过了一些非常明显的事情,但经过很多次尝试后,我仍然无法正常工作。我尽量在我的描述中尽可能具体,但我可能忘记提及某些内容,所以如果您想知道其他内容,只需提出问题,我会很乐意提供更多详细信息。

谢谢。

回答

3

问题是indexData[id] = parentData您在哪里使indexData [id]是对parentData的引用,然后在循环的下一次迭代中修改parentData。

由于父数据不是一个简单的数组(它至少包含一个数组或对象),因此不能简单地使用slice(0)来创建副本。你必须编写你自己的拷贝函数,或者使用一个有一个的函数库。

+0

因此,如果它在'parentData.meta [2] = separateList [i] .meta'中出现,那么实际上这个问题与'indexData [id] = parentData'事件有关呢? –

+0

是'separateList [i] .meta'数组还是对象,还是简单类型?如果它总是一个简单的类型,那么这行就没有问题,如果它可以是一个对象或一个数组**,并且**稍后在代码中修改'separateList [i] .meta',那么您也会遇到同样的问题在两条线上。 – Paulpro

+0

好的!得到它的工作。我刚刚创建了一个虚拟对象,我将其分配给indexData [id],然后我修改它,如下所示: indexData [id] = {name:“FOO”,parent_id:2,rule:“11”,meta :[null,null,null,null],childCount:0} 'indexData [id] .meta [2] = separateList [i] –

3

我的猜测是,这是你的问题在于:

// Just copying the passed parent object's data 
var parentData = data; 

这不,事实上,复制数据;相反,它创建了对data的引用,因此对parentData所做的任何修改也将更改为data。如果您想“克隆”对象,则必须手动执行此操作,或者找到具有此功能的库。

+0

//修改自http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone 函数CloneObject(obj){ if(obj === null || typeof(obj)! ='object'){return obj; } var temp = {};如果(密钥){temp [key] = obj [key]; } } return temp; } – JoshNaro