问题
I'm making a 2D, top-down Zelda style web rpg single player in JavaScript.
When the player (purple shirt) walks near a cat, it will "rescue" it... which basically removes the animalContainer
from the ContainerOfAnimals
(thereby removing animalContainer's BMP from the stage), and then add the id of that animalContainer to a rescuedTotal_Array
...
The weird thing is, In the pic below, I'm able to rescue animalContainer2
and then rescue animalContainer1
... But if I go from animalContainer1
to animalContainer2
, it throws a
Uncaught TypeError: Cannot read property 'id' of undefined` error.
... Basically:
Working way: get ID 22, then up to ID 21 ->>> One thing I notice with this is that the element name doesn't change for the ID... not sure why... so for the broken way... it may not be able to even associate element name animalContainer2
with an ID? But I don't know how the ID and the name could get disassociated like that..
ID in rescued array...: 22, element name: animalContainer1, rescued array length: 2, elem index pos: 0, index: 0
ID in rescued array...: 21, element name: animalContainer1, rescued array length: 2, elem index pos: 1, index: 0
Broken way- throws error: get ID 21, then down to ID 22
ID in rescued array...: 21, element name: animalContainer1, rescued array length: 1, elem index pos: 0, index: 0
1. Uncaught TypeError: Cannot read property 'id' of undefined
Code Snippet:
function grabIt(NPC_id, index) {
//check if NPCid already exists in array before adding...
if ($.inArray(ContainerOfAnimals.children[index].id, rescuedTotal_Array) == -1) {
rescuedTotal_Array.push(ContainerOfAnimals.children[index].id);
}
if (rescuedTotal_Array.length == 2) {
for (var z = 0; z < rescuedTotal_Array.length; z++) {
console.log("ID in rescued array...: " + rescuedTotal_Array[z] + ", \n element name: " + ContainerOfAnimals.children[index].name + ", rescued array length: " + rescuedTotal_Array.length + ",\n elem index pos: " + z + ",\n index: " + index);
}
}
//when I remove the first added element to rescuedTotalArray... the 2nd element's index assumes first added element's index... (goes from 1 to 0)
console.log(index);
console.log("element removed: " + ContainerOfAnimals.children[index]);
stage.update();
ContainerOfAnimals.removeChild(ContainerOfAnimals.children[index]);
updateHUD();
}
I have no idea why the order in which I store elements in the array/remove them from the stage would matter...
EDIT: I feel I can solve this issue by removing element from ContainerOfAnimals by element ID instead of by index... by Container object offers no getChildID()
function...
so I tried:
var childToRemove = document.getElementById(ContainerOfAnimals.children[index]);
console.log(childToRemove);
ContainerOfAnimals.removeChild(childToRemove);
console.log(childToRemove) gives me null
for children
But doing this: console.log(ContainerOfAnimals.children[index].id);
gives me id 21
, which is the correct id...
回答1:
Beware that EaselJS elements aren't DOM elements.
Supposing you want to remove an element by its id, I'd suggest this :
function removeElementById(container, id) {
for (var i=container.getNumChildren(); i-->0;) {
if (container.getChildAt(i).id===id) {
container.removeChildAt(i);
return true;
}
}
return false;
}
But using the id might not be the best architectural solution. In my EaselJS program I keep a reference to the objects themselves so that I don't have to search them.
回答2:
It may be possible that your rescuedTotal_Array
is an associative Array (or was morphed to one) and could contain something like:
rescuedTotal_Array = [1:object,2:object,object:object]
The array above has the length of 3. But you cannot access the third element via index 2, because its index is some kind of object.
Try to dump the content of your rescuedTotal_Array
before accessing it (so you can see if everything is ok). This is not a solution, but it may help you so that you can find the error by yourself. Use something like
for (index in rescuedTotal_Array) {
if (rescuedTotal_Array.hasOwnProperty(index)) {
console.log(rescuedTotal_Array[index]);
}
else {
console.log("no entry found for index: "+index);
}
}
回答3:
I am not entirely sure whatever if this is the case (I can't know it without taking a look at your whole program), but it could be this:
I assume that your "ContainerOfAnimals" is a HTML element and that you are retrieving it's child nodes using it's .children -property. The thing is that .children -property returns a "live list"!
Let me demonstrate:
var children = ContainerOfAnimals.children;
console.log(children.length) // 2;
ContainerOfAnimals.removeChild(children[0]);
console.log(children.length) // 1;
Let's say that you remove the very first child of ContainerOfAnimals. What happens? The children -list has now changed so that the second element becomes the first element, third element becomes the second element etc...
You could fix this by using a static array containing all the children and like this:
var children = [].slice.call(ContainerOfAnimals.children);
console.log(children.length) // 2;
ContainerOfAnimals.removeChild(children[0]);
console.log(children.length) // 2;
Now removing the element from the DOM -tree does not remove the element from the children array (which is static). Remember, that [].slice.call does not work in IE8 or lower.
Let me know if this was the problem. I have not enough points to comment, so I had to make a full post :)
回答4:
HY,
Try for statement like this:
for(var z = rescuedTotal_Array.length; z >= 0; z-- )
If you noticed I just turned it around. It starts at the and going backwards. It is stupid but, maybe this error is just that :)
Let me know how it goes!
Regards
来源:https://stackoverflow.com/questions/18254816/javascript-extremely-confused-on-removing-elements-from-container