I have a array is product
product[1][...]
product[2][...]
...
And I have a other array is hold.
My command:
hold['product'] = product;
for(i in product){
delete product[i];
}
for(i in hold['product']){
alert(i);
}
And Nothing happen. hold array doesn't have any element when I delete element of product array?
That is expected behavior. Complex types such as arrays are passed by reference in JavaScript. So when you assign an array to another variable, you are really assigning the reference. In order to avoid it, you should assign a copy of the original.
Try:
hold['product'] = product.slice(0);
try this one
var hold['product'] = product.slice();
It will create new copy of array on heap memory.So both array have their own copy
for more please check this one slice
Related
I have an array like this
var list =['lemon', 'apple'];
list['yuck'] = 'durian';
list.forEach(function(i){
console.log(i);
});
The out put is
lemon
apple
So where is durian?
This question is not about how use array properly, I just find it odd that we able to do that, what's really going on here?
forEach iterates on an array's elements, that is the properties identified by a positive integer. 'yuck' is a string which can't be converted to an integer.
If you really want to iterate on all values, you can do this:
for (var key in list) {
console.log(list[key]);
}
But it breaks all the optimizations of arrays. You should probably use a Set or an object instead.
Because that's not how you add a value to a javascript array. You have to use the method Array.prototype.push()
var list = ['lemon', 'apple'];
list.push('durian');
list.forEach(function(i){
console.log(i);
});
list['yuck'] = 'durian';
Here the syntax says add the text durain to a property yuck.
Here you are adding key values. This is how you assign values to a object.
The above line will throw an exception as you cannot add key values to array. So your array is never modified.
And this one
list.forEach(function(i){
console.log(i);
});
You are looping the initial array. Hence same values are printed.
On other hand you can use.
list.push('durian')
Or
list[2] = 'durian'
Newbie here...be nice.
I have an empty object that will get pushed into an array.
listView = {};
I add properties to it.
listView.code = code;
listView.description = description;
I push the results object into an array.
listy.push(listView);
Each time I enter a new selection in step #2 it overwrites the object instead of adding the new object properties to the array. It also increments the index by one, so it just repeats...
[{"code":"I77.812","description":"Thoracoabdominal Aortic Ectasia"}]
[{"code":"I77.811","description":"Abdominal Aortic Ectasia"},{"code":"I77.811","description":"Abdominal Aortic Ectasia"}]
[{"code":"I06.1","description":"Rheumatic aortic insufficiency"},{"code":"I06.1","description":"Rheumatic aortic insufficiency"},{"code":"I06.1","description":"Rheumatic aortic insufficiency"}]
The array should contain three different objects. But instead it has three copies of the newly added one...
How should I be adding the new choice objects so that they don't get overwritten?
You are always adding a reference to the same object, and changing that same object, instead of adding new objects. See this:
var a = [];
var o = {};
for (var i = 0; i < 5; i++) {
o.id = i;
a.push(o);
}
a
// => [{"id":4},{"id":4},{"id":4},{"id":4},{"id":4}]
But
var a = [];
for (var i = 0; i < 5; i++) {
var o = {};
o.id = i;
a.push(o);
}
a
// => [{"id":0},{"id":1},{"id":2},{"id":3},{"id":4}]
The difference is, the second code always makes a new object that is distinct from all other objects already in the array.
As a metaphor, imagine a theatre director in casting. He turns to an actor, says "You... you'll be Romeo.". Then he looks at the same actor, says "You... you'll be Mercutio. Here, Mercutio, take this sword. Romeo... who told you to get a sword?!?" completely failing to realise that, if Romeo and Mercutio are the same person, if one of them picks up a sword, the other does it too.
Seeing as you declared yourself a 'newbie' i figured i'd take a bit more time explaining. When you push an object to an array, you don't copy the object. You just tell the array where to find the object (a reference). If you push the same object 3 times, the array just has 3 indexes at which it finds the same object. There's several ways around this, the easiest being that you declare the variable inside the loop
for (var i=0;i<3;i++){
var listView = {};
listView.id = i;
listy.push(listView);
}
This way listView is a different reference each time. The other way is to create a new object when you push
listy.push({id:listView.id, description:listView.description});
which works because simple variables are 'copied' into the array and not referenced.
your assignment of the properties of an object are simply replacing the existing properties. wh en you push the object in the array by name, you are push a reference to the object and not a value. This is why all the elements in the array are the same. You need to create a new object every time you push. Something like this should work for you.
listy.push({code:code, description:description});
try this :
listy.push({
code:listView.code,
description : listView.description
})
In my code I have used pass by value.
In your code , you are using Objects which are passed by reference .
You are adding same reference again and again so at the end you will get an array having all the values of same object .
To understand more about pass by value and pass by reference you can reffer this link :
Pass Variables by Reference in Javascript
I would like to use $parse in angularJS to dynamically create a scope variable which references an array and then push to that array; but $parse's assign method does not seem to do the trick.
$scope.life.meaning = [];
var the_string = 'life.meaning';
// Get the model
var model = $parse(the_string);
Would like to push '42' into the array. So the following won't work:
// Assigns a value to it
model.assign($scope, 42);
Are there any other ways to do this? Thanks.
Your example is overwriting the assignment for that object on the scope. The $parse can be used to either get or make assignments. What you need to do it get the array and then push the item onto the array that you got. Because JavaScript arrays are pointers in memory, adding to the array that you retrieved will do the trick.
//get the current value as evaluated against the $scope
var ar = $parse('life.meaning')($scope);
//if the value isn't an array then make it one
if (!Array.isArray(ar)) {
ar = [];
$parse('life.meaning').assign($scope, ar);
}
//add an item to the array
ar.push(42);
Copying an array of objects into another array in javascript using slice(0) and concat() doesnt work.
I have tried the following to test if i get the expected behaviour of deep copy using this. But the original array is also getting modified after i make changes in the copied array.
var tags = [];
for(var i=0; i<3; i++) {
tags.push({
sortOrder: i,
type: 'miss'
})
}
for(var tag in tags) {
if(tags[tag].sortOrder == 1) {
tags[tag].type = 'done'
}
}
console.dir(tags)
var copy = tags.slice(0)
console.dir(copy)
copy[0].type = 'test'
console.dir(tags)
var another = tags.concat()
another[0].type = 'miss'
console.dir(tags)
How can i do a deep copy of a array into another, so that the original array is not modified if i make a change in copy array.
Try
var copy = JSON.parse(JSON.stringify(tags));
Try the following
// Deep copy
var newArray = jQuery.extend(true, [], oldArray);
For more details check this question out What is the most efficient way to deep clone an object in JavaScript?
As mentioned Here .slice(0) will be effective in cloning the array with primitive type elements. However in your example tags array contains anonymous objects. Hence any changes to these objects in cloned array are reflected in tags array.
#dangh's reply above derefences these element objects and create new ones.
Here is another thread addressing similar situation
A nice way to clone an array of objects with ES6 is to use spread syntax:
const clonedArray = [...oldArray];
MDN
Easiest and the optimistic way of doing this in one single line is using Underscore/Lodash
let a = _.map(b, _.clone)
You just need to use the '...' notation.
// THE FOLLOWING LINE COPIES all elements of 'tags' INTO 'copy'
var copy = [...tags]
When you have an array say x, [...x] creates a new array with all the values of x. Be careful because this notation works slightly differently on objects. It splits the objects into all of its key, value pairs. So if you want to pass all the key value pairs of an object into a function you just need to pass function({...obj})
Same issue happen to me. I have data from service and save to another variable. When ever I update my array the copied array also updated. old code is like below
//$scope.MyData get from service
$scope.MyDataOriginal = $scope.MyData;
So when ever I change $scope.MyData also change $scope.MyDataOriginal.
I found a solution that angular.copy right code as below
$scope.MyDataOriginal = angular.copy($scope.MyData);
I know that this is a bit older post but I had the good fortune to have found a decent way to deep copy arrays, even those containing arrays, and objects, and even objects containing arrays are copied... I only can see one issue with this code is if you don't have enough memory I can see this choking on very large arrays of arrays and objects... But for the most part it should work. The reason that I am posting this here is that it accomplishes the OP request to copy array of objects by value and not by reference... so now with the code (the checks are from SO, the main copy function I wrote myself, not that some one else probably hasn't written before, I am just not aware of them)::
var isArray = function(a){return (!!a) && (a.constructor===Array);}
var isObject = function(a){return (!!a) && (a.constructor===Object);}
Array.prototype.copy = function(){
var newvals=[],
self=this;
for(var i = 0;i < self.length;i++){
var e=self[i];
if(isObject(e)){
var tmp={},
oKeys=Object.keys(e);
for(var x = 0;x < oKeys.length;x++){
var oks=oKeys[x];
if(isArray(e[oks])){
tmp[oks]=e[oks].copy();
} else {
tmp[oks]=e[oks];
}
}
newvals.push(tmp);
} else {
if(isArray(e)){
newvals.push(e.copy());
} else {
newvals.push(e);
}
}
}
return newvals;
}
This function (Array.prototype.copy) uses recursion to recall it self when an object or array is called returning the values as needed. The process is decently speedy, and does exactly what you would want it to do, it does a deep copy of an array, by value... Tested in chrome, and IE11 and it works in these two browsers.
The way to deeply copy an array in JavaScript with JSON.parse:
let orginalArray=
[
{firstName:"Choton", lastName:"Mohammad", age:26},
{firstName:"Mohammad", lastName:"Ishaque", age:26}
];
let copyArray = JSON.parse(JSON.stringify(orginalArray));
copyArray[0].age=27;
console.log("copyArray",copyArray);
console.log("orginalArray",orginalArray);
For this i use the new ECMAScript 6 Object.assign method :
let oldObject = [1,3,5,"test"];
let newObject = Object.assign({}, oldObject)
the first argument of this method is the array to be updated,
we pass an empty object because we want to have a completely new object,
also you can add other objects to be copied too :
let newObject = Object.assign({}, oldObject, o2, o3, ...)
I have to push elements in an associative array from another array after some processing and I'm doing something this:
for(var i in this.aNames) {
var a = this.aNames[i];
// some processing on a
aList[i] = a;
aList.push(i);
}
But it's not giving me the proper array.
EDIT :
Here aNames is an associative array like this
'1232':'asdasdasd',
'6578':'dasdasdas'
...... and so on of about 100 elements.
I'm using for here as I want to do some changes in every element of the array.
Then I'm displaying the result array on the page but it's showing the key value together with the array data.
I.e. it should only display asdasdasd or asdasdasd but it's displaying keys too, like 1232 asdasdasd 6578 dasdasdas.
There are multiple things which may go wrong...
Primarily, make sure that this is pointing to the correct context and that this.aNames is actually returning a complex object (associative array).
Also, what's aList? Is it an array? If it is, push should append your array with the key of the current member (the member's name).
If you want to append the values of the members on your source object, you need to do something like this:
var obj = {name: 'dreas'},
arr = []; // arr is an array
arr.push(obj["name"]); // arr now contains a single element, 'dreas'
In your for..in construct, you are both adding elements to an alleged array (aList) with push but also creating new members on your array (with the subscript notation, aList[i] = "asd" since i in this case (for..in iteration) refers to the member's name).
So, what you need to do is decide if you want to add elements to an array or members to an object, not both.
If you just want to clone an array, use a for loop. If on the other hand you want to clone an object, it's not that trivial because members can also be complex objects containing their own members, and simply doing arr[i] = obj.member will only copy a pointer to arr[i] if member is a complext object, not a value type.
Just to make sure my terminology is understandable:
var anObject = {name: "dreas"},
anArray = [1,2,3];
anObject["name"] <= member (results in "dreas")
anArray[1] <= element (results in 2)