Javascript .push() variable reference/destruction [duplicate] - javascript

This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 5 years ago.
Ran in to this and I can't find documentation explaining the change- why does .push() change an array when it's applied to a new array that is set equal to that original array?
ex:
var arr = [1, 2, 3, 4, 5]
var newarr = arr
newarr.push(3)
console.log(newarr) //returns [1, 2, 3, 4, 5, 3] as expected
console.log(arr) //returns [1, 2, 3, 4, 5, 3] as well
What's happening here? I'm not applying any methods to arr (that I can see). It looks like arr and newarr are still linked in a way that doesn't apply to other variables, or .push() is invoking the newarr assignment line somehow?
For contrast, this is analogous to what I was expecting-
var x=6
var y=x
y=y*6
console.log(y) // now 36
console.log(x) // still six

The difference between your examples is arrays are mutable, and numbers aren't.
When you write var newarr = arr, you're literally saying that newarr is arr. You need to make a copy of the array to get the behavior you expect.
With the number example, since numbers are immutable, you're never changing the numbers themselves.

To do that you should use the splice method, this method will create a copy of your array, not changing the original.
Nevertheless you should know that when you do the attribution newarr = arr you're not creating a new independent variable that is an array, rather you're created another pointer to the same array.

Related

Why doesn't indexOf find an array within the searched array? (Need explanation not solution) [duplicate]

This question already has answers here:
indexOf( object) in javascript [duplicate]
(6 answers)
indexOf method in an object array?
(29 answers)
Closed 3 years ago.
I'm learning Javascript and would like to understand why indexOf isn't finding the array within the searched array. (An explanation, theory etc. is the goal for this one, no alternative code or other solutions are needed)
In looking for the array [1, 2] within the array "arr" - why does indexOf not see the array?
Does this have to do with values vs.
const o = { name: "Ethan" };
const arr = [1, 5, "a", o, true, 5, [1, 2], "9"];
console.log(arr.indexOf([1, 2])); //returns -1 expected 1
Expected a return of 1, instead received -1. Why?
Anyone able to share the details/theory/computer science aspect of why this is the case?
The answer at: indexOf( object) in javascript addresses objects, not arrays
The answer at: Looking for a good clear explanation for why this doesn't work addresses functions and for loops, not the indexOf method
The answer at: indexOf method in an object array? addresses objects and offers solutions to change how its being done, however I don't see an explanation as to why two arrays that appear to be identical are not being identified as being identical.
The reference of: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Using_the_Equality_Operators addresses comparison operators - and perhaps the answer lies within the realm of strict equality. And this may be where the lack of understanding on my part is. Is the [1, 2] that is being searched for somehow being construed as different than the one that is in the array 'arr' ?
The reference of: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Description addresses indexOf but doesn't appear to share any guidance on an array within another array. (Jagged array?)
I'm new to Javascript (as you can tell) and am looking to understand in detail why and/or how in the example the search for [1, 2] doesn't match the element of the arr array that is also [1, 2]
Because
indexOf() compares searchElement to elements of the Array using strict
equality (the same method used by the === or triple-equals operator).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf#Description
and
Two distinct objects are never equal for either strict or abstract
comparisons.
An expression comparing Objects is only true if the operands reference the same Object.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Using_the_Equality_Operators
Whenever you compare two array using == or === it checks whether the both operands refer to the same object(array) in the memory. indexOf method internally uses === operator.
The array you pass to the function doesn't not refer to array which is element of another array although their elements are same.
You could use Array#indexOf with the same array of take another approach with Array#findIndex and check if the item is an array, the length and if each value is equal.
const
o = { name: "Ethan" },
a = [1, 2],
arr = [1, 5, "a", o, true, 5, [1, 2], a, "9"];
console.log(arr.indexOf(a)); // 7
console.log(arr.findIndex(item =>
Array.isArray(item) &&
item.length === a.length &&
a.every((v, i) => a[i] === v)
)); // 6

I have a nested array and need to reduce it to one dimensional array [duplicate]

This question already has answers here:
Merge/flatten an array of arrays
(84 answers)
Closed 4 years ago.
I want to reduce the dimensions of my array from array of arrays to a single array. The structure may be heavily nested.
I tried using reduce and map functions and running a loop, but it is very complicated. Wanted to know if there is a simpler solution
Input example: a = [[1],[2,3,['abc']],[5,[6,['def']]]]
Output expected: a = [1, 2, 3, "abc", 5, 6, "def"]
I think this would be a great example to use the new flat function in arrays
refer [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat]
let a = [[1],[2,3,['abc']],[5,[6,['def']]]]
a = a.flat(Infinity); // since the nesting may be highly deep
You can use a recommended polyfill since the browser support is not very high.
Alternatives are to use reduce and concat, which is explained in the link above.
//to enable deep level flatten use recursion with reduce and concat
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
flattenDeep(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
You can use flat with the level of nesting to make it a single array
var a= [[1],[2,3,['abc']],[5,[6,['def']]]];
console.log(a.flat(3))

This array reassignment does not make sense to me [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 4 years ago.
So Im trying to solve this algorithm where I have to sum 4 numbers from given array(first parameter) in order to get second passed parameter, and Im doing it in a pretty stupid way (question not about solving the algorithm).
Question is: why I can't delete values from array and recreate/reassign itself again, hope that make sence. Is it just how Javascript works or I did something wrong?
Thanks in advance!
function foo(arr1, sum){
let arr = arr1;
for(let i=0; i<9999;i++){
let val1=arr[Math.floor(Math.random()*arr.length)];
arr.splice(arr.indexOf(val1),1);
console.log(arr1);
let val2=arr[Math.floor(Math.random()*arr.length)];
arr.splice(arr.indexOf(val2),1);
let val3=arr[Math.floor(Math.random()*arr.length)];
arr.splice(arr.indexOf(val3),1);
let val4=arr[Math.floor(Math.random()*arr.length)];
arr.splice(arr.indexOf(val4),1);
if(val1+val2+val3+val4 == sum){
console.log(val1,val2,val3,val4);
return [val1,val2,val3,val4];
}
arr=arr1;
}
}
console.log(foo([2, 7, 4, 0, 9, 5, 1, 3], 20));
Actually arr1 is not the array itself but a Reference to it. If you do arr = arr1 you copy that Reference, and that Reference points to the same array as arr1. Therefore if you change the array arr is referencing, you also change the array arr1 is referencing. To copy an array:
arr = arr1.slice();

Javascript - Modify an array duplicate without modifying the original array [duplicate]

This question already has answers here:
Why does changing an Array in JavaScript affect copies of the array?
(12 answers)
Closed 8 years ago.
I'm sure this is a stupid thing, but i can't solve it.
If i do this:
var arr = [1, 2, 3, "up"];
var duplicate = arr;
duplicate[3] = "down";
console.log(arr[3]); //"down"
console.log(duplicate[3]); //"down"
So why the original array got modified too? It is related to the fact that they point to the same array?
How to modify only the duplicate?
You need to clone your duplicate array... you can use the slice() method to do it:
var arr = [1, 2, 3, "up"];
var duplicate = arr.slice(0);
duplicate[3] = "down";
console.log(arr[3]); //"up"
console.log(duplicate[3]); //"down"
The original array was modified because using var duplicate = arr just means the value of duplicate is now equal to the value of arr. Changing either one will change the value of the array.
As for copying the array and its contents, this post has a full write up How do I correctly clone a JavaScript object?

Is it better to write: var arr=[]; than var arr=new Array();? [duplicate]

This question already has answers here:
What’s the difference between "Array()" and "[]" while declaring a JavaScript array?
(19 answers)
What is the difference between `new Object()` and object literal notation?
(12 answers)
Create an empty object in JavaScript with {} or new Object()?
(10 answers)
Closed 5 years ago.
Is it better to write
var arr=[]; then var arr=new Array();
var obj={}; then var obj=new Object();
and if so, why?
I read slide lection page 36 about that idea, but no explanation was given or example why its better.
There is not a big difference between these definitions, except that the first way uses the array/object literal and the second the array/object constructor.
The array constructor may return different results, depending on the number of arguments passed in. If you pass in one argument, a new empty array is created of the length of that argument. For example:
// arr1 is the same as arr2
var arr1 = new Array(1, 2, 3, 4);
var arr2 = [1, 2, 3, 4];
alert(arr1.length == arr2.length); // true
alert(arr1[0]); // 1
alert(arr2[0]); // 1
But, passing in one argument results differently:
// arr3 has length 200 and is empty, while arr4 has length 1 and contains a number
var arr3 = new Array(200);
var arr4 = [200];
alert(arr3.length == arr4.length); // false
alert(arr3[0]); // 'undefined'
alert(arr4[0]); // 200
The speediest way to define an array or object is of course the literal way, because you don't need to call the constructor first. Anyway, the actual speed difference is negligible, really.
I did a speed test in Chrome 6, in which I defined 20 times 10000000 the same array 1, 2, 3, which gave these results:
Average speed per 10000000 calls
Array Constructor : 226.55 ms
Array Literal : 159.1 ms
As you can see, the array literal is 67,45ms faster per 10000000 array definitions.
From a typical programmer perspective, it seems that you tend to use var arr = new Array(); so as to give the feeling of typical object instantiation. But in javascript its usually good practice to use var arr = [];
Personally I dont see much difference in using both ways except for one parameter which is explained by Harmen.
Check this link too -
http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/
thomas fuchs says in his slideshow, under that video (the part saying "embrace the language" on page 20):
var arr=[] and var obj={} is better and slightly faster. I'm not sure why, but anyway, it's a pretty interesting slideshow :)

Categories