I have been working with JavaScript for quite a time, but have never encountered this issue:
var objArr = [];
var obj = {
id:null,
name:''
}
//Type 1: Why This do not work
//create an array of 5 object
for(var i=0; i<3; i++){
obj.id = i;
console.log(obj);
objArr.push(obj); //What is wrong here
}
console.log(JSON.stringify(objArr)); // Have 5 objects in the array, But if you see this object is display the last object
//output : [{"id":2,"name":""},{"id":2,"name":""},{"id":2,"name":""}]
//Type 2: Why This Works and why the above object works
var objArr=[];
//create an array of 5 object
for(var i=0; i<3; i++){
console.log(obj);
objArr.push({"id":i, "name":''});
}
console.log(JSON.stringify(objArr));
//output : [{"id":0,"name":""},{"id":1,"name":""},{"id":2,"name":""}]
Maybe I have miss understood the objects here. can you please tell me why is this behavior.
I have a jsfiddle.net Fiddle
In the first example, you have one (only one) object, obj. You are creating an array of 3 (not 5) objects, but each position in your array refers to the same object.
When you set obj.id, you are changing it for the one and only object, which is referenced at each position in the array.
In the second example, you are creating a new object each time:
{"id": i, "name":''} // this creates a new object
So it works.
Try to use something like this:
var objArr=[];
for(var i=0; i<3; i++){
var obj = {};
obj['id'] = i;
obj['name'] = null;
console.log(obj);
objArr.push(obj);
}
console.log(JSON.stringify(objArr));
You just need to create a new obj inside the first for loop. You're just editing the current obj defined outside the for loop. So each loops sets the id of the one obj to it's i value, then you're inserting a copy of that into the array, so on the next loop, each reference to the original object is changed.
Inside the for loop, I just added 'var' so obj is a new one, not the same one that is in the parent scope:
var obj.id = i;
But you may want to reformat it a bit better than that.
Related
Why is the logged Array always filled with data? Shouldnt it be an array with only one then two then three arrays in it?
var theArray=[];
function insertValues(species,quantity){
var w = window;
w[species]= [];
for(let i =0; i<quantity;i++){
w[species].push({
species:species,
randomValue:Math.random()*10
})
// console.log(theArray);
}
theArray.push(w[species]);
}
var listOfSpecies =[{animal:"Fish",amount:5},{animal:"Shark",amount:5},{animal:"Algae",amount:5}];
for(let i = 0; i<listOfSpecies.length; i++){
console.log(theArray);
insertValues(listOfSpecies[i].animal,listOfSpecies[i].amount);
}
Woah! Firstly, don't assign to window! (unexpected things will almost definitely occur).
Also, JavaScript objects (yes an array is an object, typeof [] === "object" // true) are passed by reference, not by value.
When you add to theArray, a new reference is created. When you go to log it to the console, it shows an empty array at first, but it has actually logged a reference to theArray, therefore, when you go to inspect the contents, it shows an array filled with values;
Even try the example below, the same thing occurs (albeit much simpler to follow)
var arr = [];
for (var idx = 0; idx < 3; idx++) {
console.log(arr);
arr[idx] = idx;
}
to prevent this, you would need to copy the array, like so:
var newArray = Object.assign([], theArray);
Object.assign copies the values of the array (or object), returning a new array (again, or object), but does not create a reference back to the original array or object.
Is this needed in JavaScript in any context? For example I am trying to copy an array and for some reason when I loop through it and copy the values over one by one the resulting array is missing one value; the only thing I can think of why this is so is because the array I am looping over isn't starting at the beginning.
So, is there a way to reset the internal pointer of an array in JavaScript?
Try:
var myArray = ["aa", "bb"];
var myArray2 = [];
for (var i=0, tot=myArray.length; i < tot; i++) {
myArray2.push(myArray[i]);
}
We have an empty object:
var obj = {};
I would like to make a for loop which with each iteration adds a new obj = {value: i, next: i+1}
Simply use an array of objects and for every iteration push this values on it:
var obj=[];
for(var i=1;i<10;i++){
obj.push({value: i, next: i+1});
}
This is a DEMO Fiddle.
For each iteration give the obj.value and the obj.next, take a look at JavaScript Object Properties for futher information.
Not that sure what you mean but what about this
var obj = [];
function Obj(i){
this.value = i;
this.next = i+1;
}
for (var i= 0;i<10;i++){
obj.push(new Obj(i));
}
Instead of an object of objects an array of them
In the following code sample i get a strange behavior
var data = ['xxx', 'yyy'];
for (var i in data)
{
var a = i;
var b = data[i];
}
The two first iterations works just fine. I get index "0" and "1" in i, but then it loops one extra time and now the i is "sum". Is this by design or what is this extra iteration used for? The result in my case is always empty and it messes up my code. Is there a way to not do his extra loop?
BR
Andreas
It looks like you (or some other code you've included) have added extra properties onto the Array prototype. What you should be doing is checking to see whether the object you're iterating over actually has that property on itself, not on its prototype:
for (i in data) {
if (data.hasOwnProperty(i)) {
a = i;
b = data[i];
}
}
That said, you should never use for .. in on arrays. Use a regular for loop.
See here for more information: http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
You are looping through an Array, not through an Object. For arrays it's better to use:
for (var i=0; i<data.length; i=i+1){
/* ... */
}
In your loop every property of the Array object is taken into account. That makes the for ... in loop for array less predictable. In your case it looks like sum is a property (method) that's added to Array.prototype elsewhere in your code.
There are more ways to loop through arrays. See for example this SO-question, or this one
Just for fun, a more esoteric way to loop an array:
Array.prototype.loop = function(fn){
var t = this;
return (function loop(fn,i){
return i ? loop(fn,i-1).concat(fn(t[i-1])) : [];
}(fn,t.length));
}
//e.g.
//add 1 to every value
var a = [1,2,3,4,5].loop(function(val){return val+1;});
alert(a); //=> [2,3,4,5,6]
//show every value in console
var b = [1,2,3,4,5].loop(function(val){return console.log(val), val;});
Here's a way to safely iterate.
var data = ['xxx', 'yyy'];
for (var i = 0; i < data.length; i++)
{
var a = i;
var b = data[i];
}
What you are getting is an method coming from extending the Array object, I guess you are using some library where is something like
Array.prototype.sum = function () {...};
Perhaps setting data like this would work better: var data = {0:'xxx', 1:'yyy'};
First of all data is an object. Try to add console.log(a); and console.log(b); inside your loop and you'll see.
Can some one explain the conceptual difference between both of them. Read somewhere that the second one creates a new array by destroying all references to the existing array and the .length=0 just empties the array. But it didn't work in my case
//Declaration
var arr = new Array();
The below one is the looping code that executes again and again.
$("#dummy").load("something.php",function(){
arr.length =0;// expected to empty the array
$("div").each(function(){
arr = arr + $(this).html();
});
});
But if I replace the code with arr =[] in place of arr.length=0 it works fine. Can anyone explain what's happening here.
foo = [] creates a new array and assigns a reference to it to a variable. Any other references are unaffected and still point to the original array.
foo.length = 0 modifies the array itself. If you access it via a different variable, then you still get the modified array.
Read somewhere that the second one creates a new array by destroying all references to the existing array
That is backwards. It creates a new array and doesn't destroy other references.
var foo = [1,2,3];
var bar = [1,2,3];
var foo2 = foo;
var bar2 = bar;
foo = [];
bar.length = 0;
console.log(foo, bar, foo2, bar2);
gives:
[] [] [1, 2, 3] []
arr.length =0;// expected to empty the array
and it does empty the array, at least the first time. After the first time you do this:
arr = arr + $(this).html();
… which overwrites the array with a string.
The length property of a string is read-only, so assigning 0 to it has no effect.
The difference here is best demonstrated in the following example:
var arrayA = [1,2,3,4,5];
function clearUsingLength (ar) {
ar.length = 0;
}
function clearByOverwriting(ar) {
ar = [];
}
alert("Original Length: " + arrayA.length);
clearByOverwriting(arrayA);
alert("After Overwriting: " + arrayA.length);
clearUsingLength(arrayA);
alert("After Using Length: " + arrayA.length);
Of which a live demo can be seen here: http://www.jsfiddle.net/8Yn7e/
When you set a variable that points to an existing array to point to a new array, all you are doing is breaking the link the variable has to that original array.
When you use array.length = 0 (and other methods like array.splice(0, array.length) for instance), you are actually emptying the original array.
Are you sure it really works?
I did a little experiment here, and trying to "add" an Array with a String resulted in a string.
function xyz(){
var a = [];
alert(typeof(a+$("#first").html()));
// shows "string"
}
http://www.jsfiddle.net/4nKCF/
(tested in Opera 11)