how can I concatenate two arrays in javascript? - javascript

I saw this response for extending one array with another
so I tried:
console.log(['a', 'b'].push.apply(['c', 'd']));
but it prints:
2
shouldn't it print:
['a', 'b', 'c', 'd']
if not what was i doing wrong?

if not what was i doing wrong?
First of all, .push returns the new length of the array:
var arr = [1, 1, 1];
console.log(arr.push(1)); // 4
console.log(arr); // [1, 1, 1, 1]
Second, .apply needs two arguments: The object you want to apply the function to, and an array of arguments. You only pass a single argument, so your code is basically equivalent to:
['c', 'd'].push()
I.e. you are not adding anything to the ['c', 'd'] array. That also explains why you see 2 in the output: ['c', 'd'] has length 2 and .push() doesn't add any elements to it so it still has length 2.
If you want to use .push to mutate the original array (instead of creating a new one like .concat does), it would have to look like:
var arr = ['a', 'b'];
arr.push.apply(arr, ['c', 'd']); // equivalent to Array.prototype.push.apply(arr, [...])
// ^ ^--------^
// apply to arr arguments
console.log(arr); // ['a', 'b', 'c', 'd']
See also
How to append something to an array?
Javascript push array values into another array

If your scenario allows for ES6 syntax, you can use the spread element to concatenate arrays:
var arr1 = [1,2];
var arr2 = [3,4];
var arr3 = [...arr1, ...arr2];
console.log(arr3); // Logs [1,2,3,4]

Try this:
console.log(['a', 'b'].concat(['c', 'd']));

If you're using a modern browser then you can use the spread operator, ... like so:
console.log([...['a', 'b'], ...['c', 'd']])
If you're using an older browser/no transpiler then concat is the way to go:
console.log(['a', 'b'].concat(['c', 'd']))

As there seems to be a general misunderstanding here about the use of various array appending methods I will add to it with the safest alternative to ES6's introduction of the spread operator
Functional language
Functional languages were developed to simplify code development allowing programmers and systems engineers to define functions to replace common operations/algorithms.
JS is a functional language, you write functions to make life easier, save you typing and making the program easier to test and validate, so why fight it with dangerous alternatives .
The mistake being made in the answers (with the exception of Jonathan Michalik answer) is they are all trying to either coerce the language into doing something that should be done by a function (Function.apply), or providing a solution without explanation of what it is doing (Array.concat).
Write a function to append arrays, for example.
function appendArray(array,array1){ // adds the items in array1
// array1 can be any type
// to the end of array
var len,i;
array1 = [].concat(array1); // ensure array1 is an array
len = array1.length;
i = 0;
while(i < len){
array[array.length] = array1[i++]; // this is 2* quicker than invoking push
}
return array;
}
For the 60 seconds it takes to write, or less to include as part of a general library you have created a safe and general purpose array append function.
log(appendArray([0, 1, 2, 3], 4)); // 0,1,2,3,4
log(appendArray([0, 1, 2, 3], [4, 5, 6])); // 0,1,2,3,4,5,6
Now to why the other answers are not good solutions.
Array.concat
is the safer option, and should be used if you are in control of all references to the array. It suffers from the fact that it creates a new array when it is used.
var array1 = [1,2,3];
var array2 = [4,5,6];
array1 = array1.concat(array2); // 1,2,3,4,5,6
Many are under the mistaken belief that the concat( array2 ) is added to array1, it is not, it is added to a copy of array1. If you have other references to the original array then you end up creating a copy of the concatenated array, while the original array remains in memory.
function doSomething(array){
... generate some info
array.concat(info);
}
var myArray = [...someData]; // the array
var myObject.setArray(myArray); // create a new referance to the array in myObject
myArray = doSomething(myArray); // adds info via concat to the array.
It is not immediately apparent, but you now have two arrays the original inside myObject, and the concatenated version in myObject which may store the array referance in closure, that you can not change or delete unless you dereference all associated context. Nor do you know how many references to the original array exist.
Function.apply()
There are many reasons not to use this function but of particular note is using it on the Array.push function. It suffers from indeterminacy if you use it without type checking the arrays.
var myArray = [1,2,3,4];
var data = getSomeData(); // may return array or array like data
myArray = doSomeWorkOn(myArray); // the spec says this may return undefined
myArray.push.apply(myArray,data); // what happen here is indeterminate and
// depends on the JS context, the JS mode
// and the JS version
Without vetting myArray for undefined you can not predict what the result of apply will be. It could throw and error, or it may silently fail if the global scope has a push function and you are not in strict mode.
Without knowing the JS version ES5 or ES6 the apply may have pushed one object data onto myArray, or all the items in data ES5 does not recognise array like objects as arrays for Function.apply while ES6 does. So you must vet myArray, or data to be of the correct type for the current JS version.
Arguments have limits that are dependent on the current JS context, there is also inconsistency between JS context's handling of long argument lists. Some will throw an error, others will simply truncate the arguments.
var myPixelData = [];
myPixelData.push.apply(myPixelData,getSomePixelData()); // what will happen????
This may throw, or it may work, or it may have only pushed 65535 items onto the array, or more, or less. You will have to wrap it in a try catch, and vet the results against the length of the array returned by getPixelData. All the added complexity just to make it easier???
So why use Function.apply on Array.push or use Array.concat when it is so much easier to write a function to do what you want and save you from a long list of problems, ambiguities, and errors.

You should try this:
a= ['a', 'b'];
b= ['c', 'd'];
a.push.apply(a,b);
console.log(a);

you should use variables like so
<script type="text/javascript">
var arr1=['a', 'b'];
var arr2=['c', 'd'];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1);
</script>

Related

I should be getting [[1,0],[0,0]] why am I getting [[1,0],[1,0]]? [duplicate]

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));

How to get only value from global variable? [duplicate]

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));

Array Contains Multiple Instances of Same Array When Pushing Array Javascript [duplicate]

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));

Since const is not usefull to create an immutable array in JavaScript (I don't know exactly why), what is the best way to create an Immutable array? [duplicate]

This question already has answers here:
Immutable Hash and Array implementation in JavaScript?
(4 answers)
Closed 4 years ago.
This question has nothing to do with This question in my opinion, I'm trying to understand some behavior about the javascript core, I don't want a library or something.
I'm trying to understand why this code actually modify const originalArray
const originalArray = [0, 2, 1, 1, 1];
var newArray = originalArray;
var removed = newArray.splice(0,3);
console.log(originalArray);//return [ 1, 1 ]
But at the same time this is not possible:
const originalArray = [];
originalArray = [1];
So, how can I create a truly immutable Array without a library?
The reason modifying newArray also modifies originalArray is because variables in JavaScript are just references to objects. When you say newArray = originalArray, you're not copying the array, you're copying the reference. So when you say newArray.splice(0, 3), you're modifying the array referenced by newArray, which originalArray also references.
Similarly, in JavaScript, the word const refers to the reference being constant, not the underlying object. That is to say, you can call mutating methods like .splice on a const variable with no issues. It's when you try to reassign the variable using = or similar that you run into errors.
As others have noted, Object.freeze(_) will make it so you cannot modify the inner object, achieving "immutability" in that you will not be able to modify the underlying object.
For example, if you do the following:
const originalArray = Object.freeze([1, 2, 3]);
let newArray = originalArray; // you can easily use `const` here, but I don't want to confuse the two concepts
newArray.splice(0, 3); // TypeError: Cannot add/remove sealed array elements
If you want a copy of the array that you can modify without modifying the original array, Object.freeze alone will not help you. You will want to "deep copy" the array, which can be done through various methods (easily Google-able, so I will redact them as this answer is getting longer than hoped).
You could use Object.freeze for that.
const arr = Object.freeze([1, 2, 3]);
console.log(arr);
arr[1] = 7;
console.log(arr);
const isn't creating a constant variable, like you think, it creates immutable binding. If you write const arr = [] and then arr = {}, you'll get the error. Even Object.freeze freeze only the top level. For example:
const x = Object.freeze([1, 2, 3, [3, 4, 5]]);
x[3].push(20);
console.log(x)
You will get [ 1, 2, 3, [ 3, 4, 5, 20 ] ], if you want it to be completely immutable you have to freeze it recursively, but it hits the performance.
You can also create a copy of the array like that and use the new one
const x = [1,2,3,4,5]
const y = x.slice(0, x.length)

Attaching a function to an array

var primes=[2,3,5,7]
primes.sync = function(){this[0]=23;}
primes // => [2, 3, 5, 7]
primes.sync()
primes // => [23, 3, 5, 7]
This seems to work perfectly in Chrome.
Are there any reasons to not use this syntax/"feature"? Also, can I count on primes to be behave as a normal array (e.g. when passing it to a function that expects an array)?
This is why I want to use it:
Say I have a peopleList in my program. Functions all over the app will use it like an array. Then, suddenly, I do a POST to the server. I then want the array to query the server directly, and update itself. This would allow for some very elegant code in my angular.js app.
The only trouble you'll likely have will be if you (incorrectly) try to use for-in to iterate the Array. As long as you use a for statement or one of the Array iterator methods to constrain the enumeration to numeric indices, there shouldn't be any trouble.
The Array will continue to behave like a typical Array.
What you would want to do is to add a function to Array.prototype, rather than adding it to an array instance. See below.
Array.prototype.sync = function(){this[0]=23;};
This way, all array instances, including those that have been initialized before adding the function, will automatically be able to use the function at once.
var a = [];
a.sync(); // TypeError: Object [object Array] has no method 'sync'
Array.prototype.sync = function(){this[0]=23;};
a.sync();
a // [23]
var b = [1,2,3];
b.sync();
b // [23, 2, 3]
However, only add those functions that are useful/meaningful/reusable to Array.prototype because it is going to be available for all array instances ever created and will be created.
If your function is going to be used by only few instances. You are better of adding them to each instance like you did above.

Categories

Resources