Related
I've written the following JavaScript:
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['b','c']
alert(copyOfMyArray); // alerts ['b','c']
var myNumber = 5;
var copyOfMyNumber = myNumber;
copyOfMyNumber = copyOfMyNumber - 1;
alert(myNumber); // alerts 5
alert(copyOfMyNumber); // alerts 4
This code declares a variable myArray and sets it to an array value. It then declares a second variable copyOfMyArray and sets it to myArray.
It performs an operation on copyOfMyArray and then alerts both myArray and copyOfMyArray. Somehow, when I perform an operation on copyOfMyArray, it appears that the same operation is performed on myArray.
The code then does the same thing with a number value: It declares a variable myNumber and sets it to a number value. It then declares a second variable copyOfMyNumber and sets it to myNumber. It performs an operation on copyOfMyNumber and then alerts both myNumber and copyOfMyNumber. Here, I get the expected behavior: different values for myNumber and copyOfMyNumber.
What is the difference between an array and a number in JavaScript that it seems changing an array changes the value of a copy of the array, where as changing a number does not change the value of a copy of the number?
I'm guessing that for some reason, the array is referred to by reference and the number by value, but why? How can I know what behavior to expect with other objects?
An array in JavaScript is also an object and variables only hold a reference to an object, not the object itself. Thus both variables have a reference to the same object.
Your comparison with the number example is not correct btw. You assign a new value to copyOfMyNumber. If you assign a new value to copyOfMyArray it will not change myArray either.
You can create a copy of an array using slice [docs]:
var copyOfMyArray = myArray.slice(0);
But note that this only returns a shallow copy, i.e. objects inside the array will not be cloned.
Well, the only possible answer — and the correct one — is that you're not actually copying the array. When you write
var copyOfArray = array;
you're assigning a reference to the same array into another variable. They're both pointing at the same object, in other words.
So everyone here has done a great job of explaining why this is happening - I just wanted to drop a line and let you know how I was able to fix this - pretty easily:
thingArray = ['first_thing', 'second_thing', 'third_thing']
function removeFirstThingAndPreserveArray(){
var copyOfThingArray = [...thingArray]
copyOfThingArray.shift();
return copyOfThingArray;
}
This is using the ... spread syntax.
Spread Syntax Source
EDIT: As to the why of this, and to answer your question:
What is the difference between an array and a number in JavaScript that it seems changing an array changes the value of a copy of the array, where as changing a number does not change the value of a copy of the number?
The answer is that in JavaScript, arrays and objects are mutable, while strings and numbers and other primitives are immutable. When we do an assignment like:
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray is really just a reference to myArray, not an actual copy.
I would recommend this article, What are immutable and mutable data structures?, to dig deeper into the subject.
MDN Glossary: Mutable
Cloning objects -
A loop / array.push produces a similar result to array.slice(0) or array.clone(). Values are all passed by reference, but since most primitive data types are immutable, subsequent operations produce the desired result - a 'clone'. This is not true of objects and arrays, of course, which allow for modification of the original reference (they are mutable types).
Take the following example:
const originalArray = [1, 'a', false, {foor: 'bar'}]
const newArray = [];
originalArray.forEach((v, i) => {
newArray.push(originalArray[i]);
});
newArray[0] = newArray[0] + 1;
newArray[1] = 'b';
newArray[2] = true;
newArray[3] = Object.assign(newArray[3], {bar: 'foo'});
The operations run on the newArray indices all produce the desired result, except the final (object), which, because it is copied by reference, will mutate the originalArray[3] as well.
https://jsfiddle.net/7ajz2m6w/
Note that array.slice(0) and array.clone() suffers from this same limitation.
One way to solve this is by effectively cloning the object during the push sequence:
originalArray.forEach((v, i) => {
const val = (typeof v === 'object') ? Object.assign({}, v) : v;
newArray.push(val);
});
https://jsfiddle.net/e5hmnjp0/
cheers
The issue with shallow copy is that all the objects aren't cloned, instead it get reference.So array.slice(0) will work fine only with literal array, but it will not do shallow copy with object array. In that case one way is..
var firstArray = [{name: 'foo', id: 121}, {name: 'zoo', id: 321}];
var clonedArray = firstArray.map((_arrayElement) => Object.assign({}, _arrayElement));
console.log(clonedArray);
// [{name: 'foo', id: 121}, {name: 'zoo', id: 321}] // shallow copy
In JS, operator "=" copy the pointer to the memory area of the array.
If you want to copy an array into another you have to use the Clone function.
For integers is different because they are a primitive type.
S.
Create a filter of the original array in the arrayCopy. So that changes to the new array won't affect original array.
var myArray = ['a', 'b', 'c'];
var arrayCopy = myArray.filter(function(f){return f;})
arrayCopy.splice(0, 1);
alert(myArray); // alerts ['a','b','c']
alert(arrayCopy); // alerts ['b','c']
Hope it helps.
Everything is copied by reference except primitive data types (strings and numbers IIRC).
You don't have any copies.
You have multiple variables holding the same array.
Similarly, you have multiple variables holding the same number.
When you write copyOfMyNumber = ..., you're putting a new number into the variable.
That's like writing copyOfMyArray = ....
When you write copyOfMyArray.splice, you're modifying the original array.
That isn't possible with numbers because numbers are immutable and cannot be modified,
You can add some error handling depending on your cases and use something similar to the following function to solve the issue. Please comment for any bugs / issues / efficiency ideas.
function CopyAnArray (ari1) {
var mxx4 = [];
for (var i=0;i<ari1.length;i++) {
var nads2 = [];
for (var j=0;j<ari1[0].length;j++) {
nads2.push(ari1[i][j]);
}
mxx4.push(nads2);
}
return mxx4;
}
An array, or an object in javascript always holds the same reference unless you clone or copy. Here is an exmaple:
http://plnkr.co/edit/Bqvsiddke27w9nLwYhcl?p=preview
// for showing that objects in javascript shares the same reference
var obj = {
"name": "a"
}
var arr = [];
//we push the same object
arr.push(obj);
arr.push(obj);
//if we change the value for one object
arr[0].name = "b";
//the other object also changes
alert(arr[1].name);
For object clone, we can use .clone() in jquery and angular.copy(), these functions will create new object with other reference. If you know more functions to do that, please tell me, thanks!
For Arrays with objects you can change the use JSON.parse and JSON.strinigfy to change the type of the array to an object refrence to a string and then back to a array without having to worry about the original array
var array = [{name:'John', age:34, logs:'[]'}, {name:'David', age:43, logs:'[3]'}];
var array2 = JSON.parse(JSON.stringify(array)); // turn object to function output
array2[0].age++;
alert(JSON.stringify(array));
alert(JSON.stringify(array2));
I've written the following JavaScript:
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray.splice(0, 1);
alert(myArray); // alerts ['b','c']
alert(copyOfMyArray); // alerts ['b','c']
var myNumber = 5;
var copyOfMyNumber = myNumber;
copyOfMyNumber = copyOfMyNumber - 1;
alert(myNumber); // alerts 5
alert(copyOfMyNumber); // alerts 4
This code declares a variable myArray and sets it to an array value. It then declares a second variable copyOfMyArray and sets it to myArray.
It performs an operation on copyOfMyArray and then alerts both myArray and copyOfMyArray. Somehow, when I perform an operation on copyOfMyArray, it appears that the same operation is performed on myArray.
The code then does the same thing with a number value: It declares a variable myNumber and sets it to a number value. It then declares a second variable copyOfMyNumber and sets it to myNumber. It performs an operation on copyOfMyNumber and then alerts both myNumber and copyOfMyNumber. Here, I get the expected behavior: different values for myNumber and copyOfMyNumber.
What is the difference between an array and a number in JavaScript that it seems changing an array changes the value of a copy of the array, where as changing a number does not change the value of a copy of the number?
I'm guessing that for some reason, the array is referred to by reference and the number by value, but why? How can I know what behavior to expect with other objects?
An array in JavaScript is also an object and variables only hold a reference to an object, not the object itself. Thus both variables have a reference to the same object.
Your comparison with the number example is not correct btw. You assign a new value to copyOfMyNumber. If you assign a new value to copyOfMyArray it will not change myArray either.
You can create a copy of an array using slice [docs]:
var copyOfMyArray = myArray.slice(0);
But note that this only returns a shallow copy, i.e. objects inside the array will not be cloned.
Well, the only possible answer — and the correct one — is that you're not actually copying the array. When you write
var copyOfArray = array;
you're assigning a reference to the same array into another variable. They're both pointing at the same object, in other words.
So everyone here has done a great job of explaining why this is happening - I just wanted to drop a line and let you know how I was able to fix this - pretty easily:
thingArray = ['first_thing', 'second_thing', 'third_thing']
function removeFirstThingAndPreserveArray(){
var copyOfThingArray = [...thingArray]
copyOfThingArray.shift();
return copyOfThingArray;
}
This is using the ... spread syntax.
Spread Syntax Source
EDIT: As to the why of this, and to answer your question:
What is the difference between an array and a number in JavaScript that it seems changing an array changes the value of a copy of the array, where as changing a number does not change the value of a copy of the number?
The answer is that in JavaScript, arrays and objects are mutable, while strings and numbers and other primitives are immutable. When we do an assignment like:
var myArray = ['a', 'b', 'c'];
var copyOfMyArray = myArray;
copyOfMyArray is really just a reference to myArray, not an actual copy.
I would recommend this article, What are immutable and mutable data structures?, to dig deeper into the subject.
MDN Glossary: Mutable
Cloning objects -
A loop / array.push produces a similar result to array.slice(0) or array.clone(). Values are all passed by reference, but since most primitive data types are immutable, subsequent operations produce the desired result - a 'clone'. This is not true of objects and arrays, of course, which allow for modification of the original reference (they are mutable types).
Take the following example:
const originalArray = [1, 'a', false, {foor: 'bar'}]
const newArray = [];
originalArray.forEach((v, i) => {
newArray.push(originalArray[i]);
});
newArray[0] = newArray[0] + 1;
newArray[1] = 'b';
newArray[2] = true;
newArray[3] = Object.assign(newArray[3], {bar: 'foo'});
The operations run on the newArray indices all produce the desired result, except the final (object), which, because it is copied by reference, will mutate the originalArray[3] as well.
https://jsfiddle.net/7ajz2m6w/
Note that array.slice(0) and array.clone() suffers from this same limitation.
One way to solve this is by effectively cloning the object during the push sequence:
originalArray.forEach((v, i) => {
const val = (typeof v === 'object') ? Object.assign({}, v) : v;
newArray.push(val);
});
https://jsfiddle.net/e5hmnjp0/
cheers
The issue with shallow copy is that all the objects aren't cloned, instead it get reference.So array.slice(0) will work fine only with literal array, but it will not do shallow copy with object array. In that case one way is..
var firstArray = [{name: 'foo', id: 121}, {name: 'zoo', id: 321}];
var clonedArray = firstArray.map((_arrayElement) => Object.assign({}, _arrayElement));
console.log(clonedArray);
// [{name: 'foo', id: 121}, {name: 'zoo', id: 321}] // shallow copy
In JS, operator "=" copy the pointer to the memory area of the array.
If you want to copy an array into another you have to use the Clone function.
For integers is different because they are a primitive type.
S.
Create a filter of the original array in the arrayCopy. So that changes to the new array won't affect original array.
var myArray = ['a', 'b', 'c'];
var arrayCopy = myArray.filter(function(f){return f;})
arrayCopy.splice(0, 1);
alert(myArray); // alerts ['a','b','c']
alert(arrayCopy); // alerts ['b','c']
Hope it helps.
Everything is copied by reference except primitive data types (strings and numbers IIRC).
You don't have any copies.
You have multiple variables holding the same array.
Similarly, you have multiple variables holding the same number.
When you write copyOfMyNumber = ..., you're putting a new number into the variable.
That's like writing copyOfMyArray = ....
When you write copyOfMyArray.splice, you're modifying the original array.
That isn't possible with numbers because numbers are immutable and cannot be modified,
You can add some error handling depending on your cases and use something similar to the following function to solve the issue. Please comment for any bugs / issues / efficiency ideas.
function CopyAnArray (ari1) {
var mxx4 = [];
for (var i=0;i<ari1.length;i++) {
var nads2 = [];
for (var j=0;j<ari1[0].length;j++) {
nads2.push(ari1[i][j]);
}
mxx4.push(nads2);
}
return mxx4;
}
An array, or an object in javascript always holds the same reference unless you clone or copy. Here is an exmaple:
http://plnkr.co/edit/Bqvsiddke27w9nLwYhcl?p=preview
// for showing that objects in javascript shares the same reference
var obj = {
"name": "a"
}
var arr = [];
//we push the same object
arr.push(obj);
arr.push(obj);
//if we change the value for one object
arr[0].name = "b";
//the other object also changes
alert(arr[1].name);
For object clone, we can use .clone() in jquery and angular.copy(), these functions will create new object with other reference. If you know more functions to do that, please tell me, thanks!
For Arrays with objects you can change the use JSON.parse and JSON.strinigfy to change the type of the array to an object refrence to a string and then back to a array without having to worry about the original array
var array = [{name:'John', age:34, logs:'[]'}, {name:'David', age:43, logs:'[3]'}];
var array2 = JSON.parse(JSON.stringify(array)); // turn object to function output
array2[0].age++;
alert(JSON.stringify(array));
alert(JSON.stringify(array2));
What’s the difference between “{}” and “[]” while declaring a JavaScript array?
Normally I declare like
var a=[];
What is the meaning of declaring the array as var a={}
Nobody seems to be explaining the difference between an array and an object.
[] is declaring an array.
{} is declaring an object.
An array has all the features of an object with additional features (you can think of an array like a sub-class of an object) where additional methods and capabilities are added in the Array sub-class. In fact, typeof [] === "object" to further show you that an array is an object.
The additional features consist of a magic .length property that keeps track of the number of items in the array and a whole slew of methods for operating on the array such as .push(), .pop(), .slice(), .splice(), etc... You can see a list of array methods here.
An object gives you the ability to associate a property name with a value as in:
var x = {};
x.foo = 3;
x["whatever"] = 10;
console.log(x.foo); // shows 3
console.log(x.whatever); // shows 10
Object properties can be accessed either via the x.foo syntax or via the array-like syntax x["foo"]. The advantage of the latter syntax is that you can use a variable as the property name like x[myvar] and using the latter syntax, you can use property names that contain characters that Javascript won't allow in the x.foo syntax.
A property name can be any string value.
An array is an object so it has all the same capabilities of an object plus a bunch of additional features for managing an ordered, sequential list of numbered indexes starting from 0 and going up to some length. Arrays are typically used for an ordered list of items that are accessed by numerical index. And, because the array is ordered, there are lots of useful features to manage the order of the list .sort() or to add or remove things from the list.
When you declare
var a=[];
you are declaring a empty array.
But when you are declaring
var a={};
you are declaring a Object .
Although Array is also Object in Javascript but it is numeric key paired values.
Which have all the functionality of object but Added some few method of Array like Push,Splice,Length and so on.
So if you want Some values where you need to use numeric keys use Array.
else use object.
you can Create object like:
var a={name:"abc",age:"14"};
And can access values like
console.log(a.name);
var a = [];
it is use for brackets for an array of simple values.
eg.
var name=["a","b","c"]
var a={}
is use for value arrays and objects/properties also.
eg.
var programmer = { 'name':'special', 'url':'www.google.com'}
It can be understood like this:
var a= []; //creates a new empty array
var a= {}; //creates a new empty object
You can also understand that
var a = {}; is equivalent to var a= new Object();
Note:
You can use Arrays when you are bothered about the order of elements(of same type) in your collection else you can use objects. In objects the order is not guaranteed.
they are two different things..
[] is declaring an Array:
given, a list of elements held by numeric index.
{} is declaring a new object:
given, an object with fields with Names and type+value,
some like to think of it as "Associative Array".
but are not arrays, in their representation.
You can read more # This Article
Syntax of JSON
object = {} | { members }
members = pair | pair, members
pair = string : value
array = [] | [ elements ]
elements = value | value elements
value =
string|number|object|array|true|false|null
In JavaScript Arrays and Objects are actually very similar, although on the outside they can look a bit different.
For an array:
var array = [];
array[0] = "hello";
array[1] = 5498;
array[536] = new Date();
As you can see arrays in JavaScript can be sparse (valid indicies don't have to be consecutive) and they can contain any type of variable! That's pretty convenient.
But as we all know JavaScript is strange, so here are some weird bits:
array["0"] === "hello"; // This is true
array["hi"]; // undefined
array["hi"] = "weird"; // works but does not save any data to array
array["hi"]; // still undefined!
This is because everything in JavaScript is an Object (which is why you can also create an array using new Array()). As a result every index in an array is turned into a string and then stored in an object, so an array is just an object that doesn't allow anyone to store anything with a key that isn't a positive integer.
So what are Objects?
Objects in JavaScript are just like arrays but the "index" can be any string.
var object = {};
object[0] = "hello"; // OK
object["hi"] = "not weird"; // OK
You can even opt to not use the square brackets when working with objects!
console.log(object.hi); // Prints 'not weird'
object.hi = "overwriting 'not weird'";
You can go even further and define objects like so:
var newObject = {
a: 2,
};
newObject.a === 2; // true
[ ] - this is used whenever we are declaring an empty array,
{ } - this is used whenever we declare an empty object
typeof([ ]) //object
typeof({ }) //object
but if your run
[ ].constructor.name //Array
so from this, you will understand it is an array here Array is the name of the base class.
The JavaScript Array class is a global object that is used in the construction of arrays which are high-level, list-like objects.
Suppose you have the following code:
var array = [1];
var array2 = array;
array2.push(2);
alert(array);
This will alert "1,2", even though I clearly declared array as [1], and then did no changes to it. It's like array and array2 gets connected, and every change I do to array2 affects array. I simply want to declare array2 with the same value as array, not connect them.
Why does this happen and how to prevent it?
Thanks in advance!
jsFiddle
The problem is, that array2 is pointing on array.
what you want is:
var array2 = array.slice(0);
This really creates a copy of "array" and does not let the variable array2 point on "array".
It's because arrays and objects in JS are "passed by reference" (actually a copy of reference), not value (as it happens with primitives). There are many ways to do it, one of them being concatting an empty array:
var array = [1];
var array2 = array.concat([]);
array2.push(2);
alert(array); // 1
alert(array2); // 1,2
See some nice answers here: Does Javascript pass by reference?
Befor all , in Javascript an array is an Object
so the array variable is pointing to an in array (that you created [1]) that has an adresse in the memory (for example #1234abc). So the variable array it self is a pointer that points to an array.
You did var array2 = array
so array2 will point to the same adress in the memory (to the same object).
In other words, array2 is array they are pointing to the same object.
To get what you want, you have to create a new array and assign the same values of array1, this is called cloning.
You can do it with this trick var array2 = array.slice(0);
array2 is a reference to the original array, so if you modify it, the original will change too.
You´ll have to set array2's value to array.slice(), which clones the original and gives you a new reference.
It is because of concept Pass by reference. Internally both the variables are pointing to same memory location. So, when you change one variable that will effect other variables as well. Try slice() method if you intend to copy only values but not reference as it is. :)
var arr = new Array();
arr[0] = "a";
var ob = new Object();
ob.prop = arr;
ob.prop[0] = "b";
//Console log arr[0] returns b
for some reason, the arr array is being changed when I change ob.prop ?
What am I missing?
As the system pointed out, ob.prop = arr is basically just giving another name for accessing the object referenced by arr. So when you modify ob.prop you are modifying the same object that arr also refers to.
EDIT: For copying an array take a look at this question:
var arrCopy = arr.slice();
As Jorge mentioned, this is happening because obj.prop is just a reference to arr, so arr and obj.prop will point to the same place in memory. So if you change either, the value in memory (which the other is pointing to) changes, thus changing both.
If you're looking to avoid this you need to do a deep copy. This will copy the values of the array into a new array, which obj.prop will point at.
There is a walk-through of how to do this in javascript here.