2013-09-09 2 views
0

Я хотел бы отметить следующее сходство с этой должностью: Dynamic deep setting for a JavaScript objectWalk и установить значение сложного объект Javascript

Однако вышеуказанный пост основан на известную структуру и глубину до объектов JavaScript и не по-настоящему динамичный. Поистине динамичный предполагает, что у вас не было никаких предварительных знаний о структуре, просто путь и значение, чтобы заменить его. Я создал довольно хороший случай использования более на JSFiddle здесь:

http://jsfiddle.net/kstubs/nJrLp/1/

function Message(message) { 
$('result').insert('<div>' + message + '</div>'); 
} 

var obj = { 
"array": [1, 2, 3], 
"boolean": true, 
"null": null, 
"number": 123, 
"object": { 
    "a": "b", 
    "c": "d", 
    "e": "f", 
    "complex_array1": [{ 
     "g": "h" 
    }, { 
     "bingo": "bongo" 
    }, { 
     "x": { 
      "complex_array2": [{ 
       "h": "i" 
      }, { 
       "j": "k" 
      }, { 
       "bingo": "bongo" 
      }, { 
       "bango": "jango" 
      }] 
     } 
    }] 
}, 
"string": "Hello World" 
}; 

var list = [{ 
"h": "i" 
}, { 
"j": "k" 
}]; 

function walk(path,value) { 
var a = path.split('.'); 
var context = obj; 

for (i = 0; i < a.size(); i++) { 
    context = context[a[i]]; 
} 

}

Прецедент:

  1. Поиск complex_array2
  2. Обновить список его к новый список (новый массив)

Новый массив - это список массивов, который должен заменить список для complex_array2. Функция javascript walk делает именно это, просматривает объект javascript до тех пор, пока не будет удовлетворен критерий пути, а затем задает значение любому независимому значению, передаваемому функции walk, однако новое значение не вставлено.

Я знаю, почему он не придерживается, потому что, когда вы проходите объект типа массива, вы теряете указатель на исходный объект. Таким образом, задача состоит в том, чтобы прошел объект javascript и не потерял контекст исходного объекта.

Спасибо за любую помощь.

Karl ..

+0

Итак ... в чем вопрос? Вам это действительно нужно, или вы просто хотите бросить вызов пользователям SO? Что вы пробовали? –

+0

var context = obj, old = obj; ... old [a [i]] = "whatever" – dandavis

+0

Это может представлять интерес - один из моих собственных ответов на немного другой вкус вопроса - http://stackoverflow.com/questions/12163160/searching- json-object-key-contains-value-then-unset-it/12170015 # 12170015 – Pebbl

ответ

0

Я использовал вспомогательную функцию для чтения сложных объектов JSON. (http://jsfiddle.net/JBBAJ/)

var object = { 
    data: { 
     users: [ 
      { 
       firstName: "White" 
      }, 
      { 
       firstName: "Black" 
      } 
     ] 
    } 
} 
var read = function(path, obj) { 
    var path = path.split("."); 
    var item = path.shift(); 
    if(item.indexOf("]") == item.length-1) { 
     // array 
     item = item.split("["); 
     var arrayName = item.shift(); 
     var arrayIndex = parseInt(item.shift().replace("]", "")); 
     var arr = obj[arrayName || ""]; 
     if(arr && arr[arrayIndex]) { 
      return read(path.join("."), arr[arrayIndex]); 
     } else { 
      return null; 
     } 
    } else { 
     // object 
     if(obj[item]) { 
      if(path.length === 0) { 
       return obj[item]; 
      } else { 
       return read(path.join("."), obj[item]); 
      } 
     } else { 
      return null; 
     } 
    } 

} 
console.log(read("data.users[0].firstName", object)); // White 
console.log(read("data.users[1].firstName", object)); // Black 
console.log(read("data.test.users[0]", object)); // null 

Функция чтения принимает путь и объект.

1

Просто переверните все, кроме последнего элемента в пути. Затем конечный элемент используется для назначения после цикла.

var i = 0; 

for (; i < a.size() - 1; i++) { 
    context = context[a[i]]; 
} 

context[a[i]] = value; 

Технически вы можете оставить декларацию i внутри for. Я просто нахожу это более ясным.

http://jsfiddle.net/nJrLp/2/

+0

Точно! Я придумал тот же ответ: http://jsfiddle.net/kstubs/nJrLp/3/ на основе замечаний Андрея. – kstubs

+0

Это не связано с этим, но способ, которым вы используете 'i', не объявляя его сначала с помощью' var', делает его глобальной. Вы действительно не должны этого делать. –

1

Причина ваш код не работает, как это написано в том, что вместо того, чтобы изменить свойство на объекте у вас есть ссылки на, вы на самом деле меняется, какой объект ваших локальных переменных указывает на.

context = context[a[i]]; 

context является указателем на объект, и это локальная переменная. Когда вы назначаете ему, вы назначаете новое значение указателя, которое теряет ссылку на предыдущий объект. Если вы хотите его заменить, вам придется ссылаться на него со своего родительского объекта.Предположим, что parent является одним из таких объектов; как только вы найти имя ключа вашего целевого объекта (скажем, вы поместили его в переменной key), можно переписать существующее значение, как, например:

parent[key] = new_value; 

Это будет разыменовать parent, найти свойство с именем, key и замените его значение (которое является указателем) с адресом памяти new_value. То, что вы в данный момент что-то вроде это работает:

var context = parent[key]; 
context = new_value; 

В этом случае вы просто изменив значение указателя локальной переменной context, а не объект, который parent[key] указывает.

+0

Нравится это: http://jsfiddle.net/kstubs/nJrLp/3/ Кажется, это работает, и это фантастика. Подключите это к реальному решению и сообщите о любых других проблемах, которые я могу найти. – kstubs

Смежные вопросы