Unwanted double assignment on array function - javascript

function myFunction()
{
var Arr2
if(Arr1!=null)
{
Arr2=Arr1
console.log("Arr2 before for: "+Arr2)
console.log("Arr1 before for: "+Arr1)
}
for(var index=-1+Arr2.length;index>=0;index--)
{
if(Arr2[index]=="to_delete")
{
Arr2.splice(index,1)
}
}
console.log("Arr1 after for: "+Arr1)
console.log("Arr2 after for: "+Arr2)
}
I create Arr2 in a function, Arr2=Arr1, the problem is that Arr1 is also being spliced during for, and from these last two console.logs i am informed that these 2 arrays are the same. (I only want to change Arr2)

When you do Arr2 = Arr1, you're just copying the reference to that array, you're not making a copy of the array itself. So both Arr1 and Arr2 will now refer to the same array.
Try changing
Arr2=Arr1
to
Arr2 = Arr1.slice()
which should copy all of the elements in Arr1 to the new Arr2. Check out Array.prototype.slice for more info.

You could just use filter Array method like this :
var arr2 = arr1.filter(x => x!="to_delete");

You are creating a reference to Arr1, not a new object.
Think of it this way:
Think of it this way: when you initialise Arr1, you're allocating it to a piece of memory on the heap. This reference is then given an address.
The assignment var Arr2 = Arr1 equals the same as saying, Arr2 is the same as Arr1 by reference. Which means it points to the same memory address.
If you want to make a copy of an object, a.k.a. pass it by value, you should use one of the following methods.
var Arr2 = Arr1.slice(0);
Keep in mind however that if your array contains objects, these are cloned by reference with this method. Example:
var Arr1 = [{a: 1, b: 2, c:3}, {d: 4, e: 5, f: 6}]
var Arr2 = Arr1.slice(0)
Arr1[0].a = 2;
console.log(Arr2[0].a) // this will output 2
If you want to easily do a deep clone without having to write the code to pass the object references by value, you can use something like lodash or just:
var Arr2 = JSON.parse(JSON.stringify(Arr1));
Which also works.

Related

copying of two arrays and console output

How come console shows "potato" instead of "JAN" when you console out arr2?
arr1[0]='Potato' is done after the line 4, so why arr2 is not equal to initial arr1? (array at line 1)
Both variables have an instance of the same array.
If you want to avoid that, make something like this instead const arr2 = [...arr1]. That will create new array with same elements as the first one.
You have to make new array from variable 1
Just try:
let arr2 = Array.from(arr1)
You can use const arr2 = [...arr1]; to immutable array clone
var arr1 = ['JAN', 'FEB'];
const arr2 = [...arr1];
arr1[0] = 'Potato';
console.log(arr2)
`

Difference between fill and fill map

I came across some code which was filling an array of objects like so:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(null).map(getObj);
console.log(arr);
However, I'm wondering what the main purpose of fill(null).map(getObj) is? It seems redundant as I can simply write the following and get the same resulting array:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(getObj());
console.log(arr);
So, I'm wondering if these two lines of code do exactly the same thing or if there is something I'm missing?
The resulting arrays (top array first method with fill + map bottom array is only using map):
Array(3).fill(getObj()) will fill your array with references to the same object, Array(3).fill(null).map(getObj) will create object per element. See the example below:
const getObj = () => {
return {a: 1, b: 2, c: 3};
}
const arr = Array(3).fill(null).map(getObj);
arr[0].b=4;
console.log(JSON.stringify(arr));
const arr1 = Array(3).fill(getObj());
arr1[0].b=4;
console.log(JSON.stringify(arr1))
When it comes to Array.fill it is stated in the documentation that:
When fill gets passed an object, it will copy the reference and fill
the array with references to that object.
So using a Array.fill with objects has somewhat limited application unless you really want to have multiple objects pointing to the same reference. In more than few use cases however that would lead to bugs if not understood.
For the 2nd case where you do Array(3).fill(null).map(getObj) this is one of the ways to create a new array based on a given arbitrary size and at the same time fill it with new objects.
The real need for the fill(null) is due to the fact that calling Array(3) would only do one thing. Create a new array and set its length property to 3. That is it!
let arr = Array(3) // returns new array with its "length" property set to 3
console.log(arr) // [empty × 3] <-- browser console
So that array now has only length and bunch of empty elements. You can't do much with it until it actually has values. Therefore the need for fill so that you give it any value and then map through it to set the values you actually want. Using Array.map and calling each iteration your function guarantees you do not have same references. You could have skipped the fill step and done something like this:
const getObj = () => ({a: 1, b: 2, c: 3})
// using array destructuring
let arr = [...Array(3)].map(getObj)
arr[0].a = 3
console.log(arr)
// using Array.from
let arr2 = Array.from(Array(3)).map(getObj)
arr2[0].a = 3
console.log(arr2)
There are somewhat shorter and get you the exact same result of filling the array with specified length with objects and not references to the same object.
The trick here is that both would "fill" the array after it is defined with undefined values instead, after which the map would fill it with the values we want.

How to copy json array and not change the original array value [duplicate]

This question already has answers here:
Cloning an object and changing values mutates the original object as well
(5 answers)
Closed 5 years ago.
How can I copy the array without changing the original array value?
var arr1 = [];
var arr2 = [];
arr1 = [{price: 10},{price: 20}];
console.log(arr1);
arr2[0] = arr1[0];
arr2[0].price += 5;
console.log(arr2);
//output arr1 = [{price: 15},{price: 20}]; Why???
//output arr2 = [{price: 15}];
deep copy the array using JSON.parse(JSON.stringify(arr1))
var arr1 = [];
arr1 = [{
price: 10
}, {
price: 20
}];
var arr2 = JSON.parse(JSON.stringify(arr1))
arr2[0].price += 5;
console.log(arr2, arr1);
My friend, you are dealing with object pointers, essentially what your doing is giving arr1[0] an alias called arr2[0]. and when you change 1 you change both. One way to fix this is to declare:
arr2=arr1
arr2.length=1;
arr2[0].price+=5;
By not referencing the object directly, but just duplicating the array, we arnt allowing the object to make pointers in memory, and the arr2.length is to get rid of the second element.
You are changing the value of arr1[0] by doing below:
arr2[0].price+= 5; // eventually arr2[0] = arr1[0] and that's why it is getting updated due to object pointers
You are not creating a new variable with the content of arr1. You are only copying the arr1 pointer to a new variable called arr2. Thus, as the object pointed by arr1 and arr2 is the same, if you modify one you modify the other.
The solution would be to create a copy of the array, for example:
arr2 = arr1.copy()

Deep copy Javascript array with properties

Using .slice(), I can deep copy a Javascript Array of primitive types, for example:
var arr = [1,2,3,4];
var newArr = arr.slice();
newArr.push(5);
console.log(arr); // [1,2,3,4]
console.log(newArr); // [1,2,3,4,5]
However, If I add a property to arr like so:
arr.prop1 = 5;
and do the same:
var arr = [1,2,3,4];
arr.prop1 = 8;
arr.prop2 = 9;
var newArr = arr.slice();
newArr.push(5);
console.log(arr); // [1, 2, 3, 4, prop1: 9, prop2: 8]
console.log(newArr); // [1, 2, 3, 4, 5]
The property values do not carry over to newArr
I have considered not using .slice() and looping over the property values of arr instead, assigning them to newArr, using :
for (var key in arr) {
if (arr.hasOwnProperty(key)) {
newArr[key] = arr[key];
}
}
console.log(arr); // [1, 2, 3, 4, prop1: 9, prop2: 8]
console.log(newArr); // [1, 2, 3, 4, 5, prop1: 9, prop2: 8]
Is this going to be the quickest way to deep copy these arrays with properties? Is there in easier or cleaner way I can do this using .slice() or another array method? I am doing this operation tens of thousands of times and want it to be as clean and efficient as possible
You are trying to mix an array and object(to make an array behave like an object).
JavaScript array has numeric indexed items.
JavaScript object has string indexed items.
Arrays have a length property that tells how many items are in the array and is automatically updated when you add or remove items to the array.But ...
var arr = [1,2,3,4], newArr = arr.slice();
arr.prop1 = 7;
console.log(arr.length);
The output is 4, though you would expect it to be 5.But arr.prop1 = 7 does not actually add to the array.Setting a string parameter adds to the underlying object.
The length property is only modified when you add an item to the array, not the underlying object.The expression newArr = arr.slice() assigns a new array to newArr, so it remains an array and behaves like a pure array.
The property values do not carry over to newArr
If you still want to proceed using mixed numeric/string indexed sequences, cloning them, try using Object.assign() function. This should be the easiest way for your case:
The Object.assign() method is used to copy the values of all
enumerable own properties from one or more source objects to a target
object.
console.log(Object.assign(newArr, arr));
The output:
[1, 2, 3, 4, prop1: 7]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
How about using Object.create(proto)
var arr = [1,2,3,4];
arr.prop1 = 8;
arr.prop2 = 9;
var newArr = Object.create(arr);
newArr.prop1 = 12;
console.log(arr.prop1) // 8
console.log(newArr.prop1) // 12
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

pushing an array into another array

I have the following arrays.
var arr1=[1,2,3];
var arr2=[4,5,6];
var arr3=[];
How would I push arr1 and arr2 into arr3 such that the result is:
arr3=[[1,2,3],[4,5,6]];
not
arr3=[1,2,3,4,5,6];
which is produced when using the .concat method.
var arr1=[1,2,3];
var arr2=[4,5,6];
var arr3=[];
arr3.push(arr1,arr2);
console.log(arr3);
var arr1=[1,2,3];
var arr2=[4,5,6];
var arr3 = [arr1,arr2];
console.log(arr3);
arr3.push(arr1);
arr3.push(arr2);
will do the work.
Anyway just follow http://www.w3schools.com/jsref/jsref_push.asp for further clarifications.
Hope this helps.
You can use push() like in the other answers or this:
var arr1 = [1,2,3];
var arr2 = [4,5,6];
var arr3 = [arr1, arr2];
console.log(arr3);
As others users have posted, the solution at your problem is use .push() method, but i would try to give you more information about these two methods.
I suggest you to read this article, is very useful for me; I recap the main information for you below.
PUSH METHOD
Push method is used when you want add one or more elements, that were input arguments, to the array that invoked the method.
A simply example is the following:
var first_array = [1, 2, 3];
var result = first_array.push(4, 5, 6);
console.log(result); // 6
console.log(first_array ); // [1, 2, 3, 4, 5, 6]
The one thing is not immediately apparent is that it returns the length of the array after adding the new values, not the modified array. (check third line: console.log(result);)
CONCAT METHOD
While push alters the array that invoked it, concat returns a new array with the original array joined with the array/s or value/s that were provided as arguments.
There are a couple of the things to note about concat and how it creates the returned array.
Both strings and numbers are copied into the array, which means that they if the original value is changed, the value in the new array will be unaffected.
This is not true for objects.
Instead of copying objects into the new array, the references are copied instead. This means that if the values of objects change in one array, they will also be changed in the other array, as they are references to the objects not unique copies.
A simply example is the following:
var test = [1, 2, 3]; // [1, 2, 3]
var example = [{ test: 'test value'}, 'a', 'b', 4, 5];
var concatExample = test.concat(example); // [1, 2, 3, { test: 'test value'}, 'a', 'b', 4, 5]
example[0].test = 'a changed value';
console.log(concatExample[3].test); // Object { test: "a changed value"}
example[1] = 'dog';
console.log(concatExample[4]); // 'a'
I have created a fiddle for you with this example.
I hope that will be helpful

Categories

Resources