Массив JavaScript не будет заполняться должным образом - PullRequest
2 голосов
/ 09 августа 2011

Я создаю расширение Google Chrome, которое использует контекстные меню в качестве основного пользовательского интерфейса.Каждый пункт меню запускает один и тот же скрипт содержимого, но с разными параметрами.В основном я сохранил каждый элемент (и соответствующие ему данные) в виде объекта JSON, который имеет следующую форму:

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

name, child_count и parent_id используются для создания иерархии, когда контекстменю построены.Данные, которые передаются в скрипт - это rule_number (int) и meta_array (массив строк).Все эти объекты хранятся в массиве с именем indexData [].

При щелчке по пункту меню предоставленный идентификатор просто используется в качестве индекса в массиве «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"], его потомкамвсе может выглядеть так ["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 как-то обрабатывает массивы по адресу, а не по значению или чему-то еще?

Может быть, я упускаю что-то действительно очевидное, но после многих попыток я все еще не могу заставить это работать должным образом.Я старался быть как можно более конкретным в своем описании, но, возможно, я забыл упомянуть кое-что, поэтому, если вы хотите узнать что-то еще, просто спросите, и я буду рад предоставить более подробную информацию.

Спасибо.

Ответы [ 2 ]

3 голосов
/ 09 августа 2011

Проблема будет в indexData[id] = parentData, когда вы делаете indexData [id] ссылкой на parentData, а затем изменяете parentData на следующей итерации вашего цикла.

Поскольку родительские данные не являются простым массивом (он содержит хотя бы один массив или объект), вы не можете просто использовать slice(0) для создания копии. Вам придется написать собственную функцию копирования или использовать библиотеку, в которой она есть.

3 голосов
/ 09 августа 2011

Я предполагаю, что именно в этом заключается ваша проблема:

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

Фактически это не копирует данные;скорее, он создает ссылку на data, поэтому любые изменения, сделанные в parentData, также изменят data.Если вы хотите «клонировать» объект data, вам придется сделать это вручную или найти библиотеку с функцией для этого.

...