Метод данных jQuery передает данные дочерним объектам

0

Увидеть действительно странное поведение с помощью функции jQuery.data(). Когда я назначаю значение родительскому элементу, ему также присваивается значение данных.

HTML:

<div id="parent" class="things" data-tallest="[]">
  <div id="child1" class="things" data-tallest="[]">
    I'm a child
  </div>
  <div id="child2" class="things" data-tallest="[]">
    I'm another child
  </div>
</div>

ЯШ:

somearray = ["child1", "child2"]
$(".things").data("tallest",[])
for (var i = 0; i < somearray.length; i++) {
  tocheck = somearray[i]
  newarray = $("#"+tocheck).parent().data("tallest")
  newarray.push(20);
  $(tocheck).parent().data("tallest",newarray)
}

console.log("Correct: parent 'tallest': "+$("#parent").data("tallest"));
console.log("Problem: child1 'tallest': "+$("#child1").data("tallest"));

См. Этот скрипт (проблема отмечена в журнале консоли):

http://jsfiddle.net/cTY3H/5/

Что ДОЛЖНО произойти:

  1. Все значения, хранящиеся в любой самой высокой переменной объекта объекта, очищаются
  2. Цикл выполняет итерацию через массив и нажимает "20" на родительский объект $("#parent") - самый высокий массив данных
  3. $("#parent").data("tallest") должны равняться [20,20] - это так.
  4. Однако, $("#child1").data("tallest") == [20,20]
  5. Ни в коем случае дочерние объекты не получают ничего привязанного к.data("самый высокий"), поэтому я не знаю, почему это происходит.

Что мне здесь не хватает?

  • 1
    Почему вы помещаете 20 в массив? То, что $(tocheck) должно быть $(tocheck) так как нет элемента $('child1') или $('child2') (вы не указали # ).
  • 0
    К вашему сведению, в действительности нет никакой причины иметь data-tallest="[]" в вашей разметке HTML, поскольку вы инициализируете все это в JS.
Показать ещё 1 комментарий
Теги:

2 ответа

2
Лучший ответ

Вы инициализируете все. things имеют точную ссылку на один и тот же пустой массив. Поэтому, когда вы меняете один, все они меняются, потому что все они указывают на один и тот же массив. Помните, что массивы назначаются и извлекаются по ссылке. Итак, эта строка:

$(".things").data("tallest",[])

.things ссылку на тот же самый массив на каждый объект .things. Измените одно, и все они меняются, что объясняет ваш результат.


Вы можете исправить это и упростить его следующим образом:

// initialize all things to have their own empty array for data
$(".things").each(function() {
    $(this).data("tallest", []);
});
["#child1", "#child2"].each(function() {
    // get reference to parent data array and push a value onto it
    $(this).parent().data("tallest").push(20);
    // you don't have to set it back because the array is by reference so already changed
});

При манипулировании массивами вы также должны быть очень осторожны, поскольку массивы передаются по ссылке. Итак, когда вы получаете данные из одного места и изменяете их, вы изменяете оригинал, потому что выборка массива не сделала копию, у нее просто была ссылка. Я не думаю, что вы кусаете вас здесь, но это очень легко, если вы попытаетесь взять данные из одного элемента, изменить его и назначить другому элементу.

  • 0
    Я не замечаю проблему tocheck ... эта строка в любом случае не нужна, так как массив, сохраненный в data() , обновляется уже по ссылке
  • 0
    @charlietfl - я думал, что назначение, возможно, не нужно, за исключением, может быть, первого раза, когда данные еще не находятся в jQasery jQuery - только в атрибуте. Затем, я думаю, что это должно быть установлено обратно, но с jsFiddle вниз я не могу проверить это легко.
Показать ещё 7 комментариев
2

Проблема здесь:

$(".things").data("tallest",[])

Вы помещаете один и тот же массив в каждый элемент данных. Таким образом, путем прототипического наследования, все они имеют ссылки на один и тот же массив.

Изменить на:

$(".things").each(function(){
    $(this).data("tallest",[])
})

Каждый имеет свой собственный уникальный массив

DEMO

Пример простого ссылочного объекта:

var a=[];
var b=a;
b.push('foo');
alert(a[0]); //foo

Ещё вопросы

Сообщество Overcoder
Наверх
Меню