Pushing array into array then handling elements inside - javascript

so I just came across this, but could anyone explain it to me, why is this phenomenon present here? I didn't find any help online...
1.So if I were to get the following two arrays:
let a = [];
let b = ['','',''];
2.and then push array b into array a three times:
a.push(b);
a.push(b);
a.push(b);
3.but then when I try to change the first element of the first array like so:
a[0][0] = 'foo';
4.then all the first element of ALL the arrays change, not just the first one, as console.log(a) outputs:
(3) [Array(3), Array(3), Array(3)]
0: Array(3)
0: "foo"
1: ""
2: ""
1: Array(3)
0: "foo"
1: ""
2: ""
2: Array(3)
0: "foo"
1: ""
2: ""
I would like to ask, why does this happen and in what way could I change an element based on its index inside of array a

b is a pointer to a mutable array, changing the array it points to will cause the other places you point to it to update as well.
You would either push copies of b into the array or create a modified copy of b when trying to mutate the value it points to.

Because you're passing b which is just a reference to an object. To have the behavior you want, change your code to be like this:
a.push(b.map((x) => x))
For more see this page.

if you console.log(b), you'll see that as well.
Try doing b[1] = "test" then check the value of a and you'll see all the b's that were pushed into there have test in them too.
b is a reference so anytime you change the value of it, you are altering the places it is referenced to.

Related

How to determine the data type of the outcome of the spread operator in javaScript?

What is the data type of the elements outputted by spread? And is it possible to call only one element after spread, like with arrays?
Here is the example:
let ages = [1,2,3,1,4];
let chars = ['a','b','c'];
console.log(ages); // shows array> (5) [1, 2, 3, 1, 4]
console.log(...ages); // shows this> 1 2 3 1 4 - ??
console.log(typeof(ages[1]));// number
console.log(typeof(chars));// object
console.log(typeof(chars[1])); //string
//console.log(typeof(...ages)); - NOT WORKING
//console.log(typeof(...ages[1])); - NOT WORKING
Thanks!
What is the data type of the elements outputted by spread?
Each member of the array will have its own type.
And is it possible to call only one element after spread, like with arrays?
The point of a spread is to take all members of an array and spread them out.
If you want to access one member, then you shouldn't be using spread in the first place.
console.log(typeof(...ages))
This doesn't make sense. typeof tells you the type of something not many things.
Use a loop instead of a spread operator if you want to do something to each member of an array.
ages.forEach(member => { console.log(typeof member); });
console.log(typeof(...ages[1]));
Also doesn't make sense. ages[1] is the number 2. It isn't an iterable object. You can't spread it. If you want the type of that element then just:
console.log(typeof ages[1]);

Unexpected behavior shown by the function concat and push

I was testing my code in goolge console and I found that concat() is not working as I have illustrated below:
var a = ["a"]; //undefined
a.concat("b","c"); // ["a","b","c"]
Now when I push some other string then that string replaces the indexes of "b" and "c"
that is[continued]
a.push("e","f"); // 3
a // ["a", "e","f"]
Did you notice 3 in the line where the string is pushed. It is interesting to me that at first we contact "b" and "c" and then, when I try to get value of say 1 index then it return undefined! and then, when we push "e" and "f" in the same array then these string replaces the indexes of concated string. Now the question is:
1) Why do these concat and push function show strange behavior?
2) Do this mean the failure of cancat function?
3) Is thiscontact function is just for nominal?
This is correct. Concat isn't modifying the array like you expect it to.
When you:
a.concat("b","c");
It returns an array of ["a","b","c"], but you aren't saving the reference (which you would do like this)
a = a.concat("b","c");
Some info from the MDN:
concat does not alter this or any of the arrays provided as arguments but instead returns a shallow copy that contains copies of the same elements combined from the original arrays.

javascript array unsure property array[index] = true/false

I came across this, understood it but still did not know what javascript property it was:
var array = [];
array[1] = true;
array[5] = true;
console.log(array) #=> [true, true]
array[0] #=> undefined
array[1] #=> true
array[2] #=> undefined
array[5] #=> true
Can someone explain this for me? Thanks
Standard arrays in JavaScript aren't really arrays at all, and one effect of that is that they're inherently sparse. That is, an array can have empty slots in it.
That's what you're creating there. After your first three lines, you have an array with two entries in it, at indexes 1 and 5, and a bunch of completely empty slots (indexes 0, 2, 3, 4). Its length property would be 6. When you try to retrieve an element that doesn't exist from an array, you get the value undefined. (This is just a specific case of JavaScript's general behavior: If you try to retrieve an object property that doesn't exist, you get the value undefined.)
The output of console.log with a sparse array will vary depending on what the implementation of console.log does with them. The comments on the question suggest that there are various different ways the console may show the array. You might look at using console.log(array.join()) to get more consistent results. That would give you ,true,,,,true, because it shows blanks for array entries that don't exist (or that contain the value undefined, but in your case, they don't exist).

jQuery splice inArray with multiple key objects

Javascript newbie here --
I have the following array:
var group = ({
one: value1,
two: value2,
three: value3
});
I want to check if array "group" is part of "groupsArray" and add it if doesn't or remove it if it does.
var groupLocate = $.inArray(group, groupsArray);
if(groupLocate ==-1){
groupsArray.push(group);
} else {
groupsArray.splice($.inArray(group, groupsArray),1);
}
This method works with single value arrays. Unfortunately, I can't get it to work in this case with three keys and values as groupLocate always returns -1.
What am I doing wrong?
Thanks.
First it helps to understand why $.inArray() didn't work. Let's try a simpler case. Paste this in to the JavaScript console in your browser on a page with jQuery loaded (such as this page we're on) and run it:
var object = { a: 1 };
var array = [ { a: 1 } ];
console.log( '$.inArray: ', $.inArray( object, array ) );
(Note the terminology: your group variable is an Object, not an Array.)
Now it looks like object is in the array, right? Why does it print -1 then? Try this:
console.log( object );
console.log( array[0] );
They look the same. How about:
console.log( '== or === works? ', object == array[0], object === array[0] );
Or even simpler:
console.log( 'Does {a:1} == {a:1}? ', {a:1} == {a:1} );
console.log( 'What about {} == {}? ', {} == {} );
Those all print false!
This is because two objects that happen to have the same content are still two separate objects, and when you use == or === to compare two objects, you are actually testing whether they are both references to one and the same object. Two different objects will never compare equal, even if they contain exactly the same content.
$.inArray() works like using an === operator to compare two objects - it won't find an object in an array unless it is the same object, not just an object with identical content.
Knowing this, does that suggest any possible ways to approach the problem? There are several ways you could write your own code to search the array for your object, or you may find it helpful to use a library such as Underscore.js which has many useful methods for arrays and objects.
For example, you could use _.findWhere( groupsArray, group ) to find the first match - with the caveat that it only compares the properties that are in the group object. For example, if group is {a:1}, it would match an object in the groupsArray array that was {a:1,b:2}.
If you need an exact match, you could combine Underscore's _.find() and _.isEqual() methods:
var index = _.find( groupsArray, function( element ) {
return _.isEqual( element, group );
});
Now one last thing to watch out for. Your code that pushes the group object onto the groupsArray array - you know that pushes the actual group object itself. It doesn't make a copy of it in the array, it's a reference to the very same object. (Ironically, this means that your original code to find group in the array would actually work in the case where you'd pushed that same group object onto the array yourself.)
If you want to make sure the elements in groupsArray are each their own independent object, and not a reference to another object floating around in your code, you can use another Underscore method to do a shallow copy:
groupsArray.push( _.clone(group) );
If group has any nested objects, though, this won't copy them. (I don't see a deep copy function in Underscore, although you could write one if you need it.)

Javascript array showing 2 values in console, only 1 when accessed

I have a Javascript array of arrays.
When I print the array to the console I get:
console.log(my_array_of_arrays);
Array[2] ->, Array[2] ->,
0: 678 0: 1168
1: 865 1: 1370
length: 2 length: 2
This shows that there are 2 items in both arrays.
Then when I access last item in the array by accessing either ".length" or my_array[1], it tells me that the array only has 1 item, and the 2nd item is undefined.
var my_array = my_array_of_arrays[1];
console.log(my_array, my_array.length, my_array[0], my_array[1]);
[1168, 1370], 1, 1168, undefined
As you can see this happens if I do it all in the same console log statement, so I know the array isn't changing.
What could be going on here, I am completely stumped.
Edited for clarity
From the console in Chrome
spo = [000,111]
(spo[0] == 000) //true
(spo[1] == 111) //true
I am not sure what else you can be doing = /
I have discovered that further down the function the value my_array[2] wasn't being set until after I called console.log().
However this has shown some weird behavior of console.log().
It doesn't necessarily show the live value of the array at the time of calling.
eg.
var my_array = [111];
console.log(my_array);
my_array[1] = 222;
This prints:
[111, 222]
When I was expecting it to print:
[111]
This means that console.log() doesn't always show the "live" representation of the real values at the time of the call.
However if I access a property on the array it will show the live values.
Example:
var my_array = [111];
console.log(my_array.length, my_array[1]);
my_array[1] = 222;
This prints as expected:
1, undefined
Guess I can't trust the console as well as I have been!

Categories

Resources