Увидеть действительно странное поведение с помощью функции jQuery.data(). Когда я назначаю значение родительскому элементу, ему также присваивается значение данных.
<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"));
См. Этот скрипт (проблема отмечена в журнале консоли):
$("#parent")
- самый высокий массив данных$("#parent").data("tallest")
должны равняться [20,20] - это так.$("#child1").data("tallest")
== [20,20]Что мне здесь не хватает?
Вы инициализируете все. 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
});
При манипулировании массивами вы также должны быть очень осторожны, поскольку массивы передаются по ссылке. Итак, когда вы получаете данные из одного места и изменяете их, вы изменяете оригинал, потому что выборка массива не сделала копию, у нее просто была ссылка. Я не думаю, что вы кусаете вас здесь, но это очень легко, если вы попытаетесь взять данные из одного элемента, изменить его и назначить другому элементу.
tocheck
... эта строка в любом случае не нужна, так как массив, сохраненный в data()
, обновляется уже по ссылке
Проблема здесь:
$(".things").data("tallest",[])
Вы помещаете один и тот же массив в каждый элемент данных. Таким образом, путем прототипического наследования, все они имеют ссылки на один и тот же массив.
Изменить на:
$(".things").each(function(){
$(this).data("tallest",[])
})
Каждый имеет свой собственный уникальный массив
Пример простого ссылочного объекта:
var a=[];
var b=a;
b.push('foo');
alert(a[0]); //foo
$(tocheck)
должно быть$(tocheck)
так как нет элемента$('child1')
или$('child2')
(вы не указали#
).data-tallest="[]"
в вашей разметке HTML, поскольку вы инициализируете все это в JS.