I have a short question, just out of curiosity.
Let's say I have an object which has an array as a property this.arr = ["one", "two", "three", ...], and I populate this array with n elements.
What will happen to all these elements if I run this.arr = [] . Are they deleted, kept in memory, leaked?
Thanks!
this.arr = [] will create a new empty array and assign it to the arr property. If there is no more reference to the previous array in the program, it will be garbage collected eventually (automatically destroyed by the JS engine). But if there is still a reference to it somewhere, it will still exist.
this.arr = [1, 2, 3, 4];
var backup = this.arr;
this.arr = [];
// backup still points to the array, so it won't be destroyed
If you just want to delete an array as you won't use it anymore, you could do this.arr = null instead.
In JS, there is no such thing as "memory leaks". You can, however, forget to get rid of an object you don't need anymore. And if that object has references to other objects which in term have references to other objects, than not a single object of the tree will get destroyed.
Most of the time, if you use temporary variables, you won't need to worry about it.
They are deleted. As a matter of fact this is a fast way to empty an array.
It would be deleted. If you assign the value of this.arr to another variable, the array would be reusable, but the other variable would have different memory address, but the address, you stored the original variable would be emptied.
They will be deleted, If the string objects are no longer referenced by anything. The string objects are therefor eligible for the garbage collection to delete/release these objects.
Related
I don't understand why assigning the array to a new value doesn't affect the new array.
I know that "push" modifies the original array, splice also, and filter or slice doesn't, this is not my question. my question is that why assigning doesn't.
i have looked through old questions answers saying it is passed by reference but again if it is passed by reference then changing it's value should affect the reference also.
const modify = (someArray) => {
// modified my array
someArray.push(1)
// modified my original array
someArray[0] = 'A'
// didn't modify my array and I want to know why.
someArray = ['whatever']
}
let myArray = ['a', 'b']
modify(myArray)
console.log(myArray) // ["A", "b", 1]
In Javascript (and Java or C#) everything is by default passed by value!
The important is to know, what the value is. This line let myArray = ['a', 'b'] creates new array in memory and put the reference to it into myArray. Now, the value of myArray is the reference to the memory where ['a', 'b'] reside.
When you pass it to modify function, the value - which is the reference - is copied from myArray to someArray. It means someArray can access the same memory segment of the same array, therefore change the values inside that array, but you cannot change the value of myArray (which is the reference to that array) from someArray.
As I've described this to beginners many times, I've found that it's best to think of Objects in Javascript as being passed and assigned as a pointer (as in the way pointers work in C/C++). So, when you do this:
let a = [1,2,3];
let b = a;
You now have two variables that each have a pointer to the same [1,2,3] array. I find it works best to think about the array existing on its own and you now have two variables that each point at that array. When you assign b = a, it doesn't make a copy of the data, it just points b at the same data that a was pointing at.
If you modify that array with something like a.push(4) or assigning like a[0] = 9, then the one and only one array that both a and b point to has been modified. So, whether you access that array from a or from b, you will see the change because both variables point at the same physical array object.
But, if you reassign some other array to b like this:
b = [9,8,7];
You've just taken a new array and put a pointer to it in b. The other variable a still points to the same original array that is used to. It hasn't been changed in any way.
When you pass an array as an argument like you are doing in your modify() function, the function argument in the function is just like the b variable in the above example. It's just another variable that points at the same array. If you modify the array itself, then both variables will point at the same modified array. But, if you reassign the argument variable to now point at some other array, only that variable is affected.
['a', 'b'] is an array. myArray is a variable that refers to that array. someArray is a variable local to modify function that will take the value of myArray (i.e. the reference to your array; so both myArray and someArray refer to the same array). As you noted, someArray.push(1) and someArray[0] = 'A' both modify the array referred to by someArray. someArray = ["whatever"] will change the reference of someArray to the new array ['whatever'], but myArray still refers to the old array. At the end of the function, someArray variable disappears (and ['whatever'] is forgotten, since nothing refers to it any more).
There is no way in JavaScript to change the reference of the variable passed into a function (as e.g. C++ can); you can only manipulate what received reference points to.
Let's say we have this object: var a = {x: 3}.
Now, if we have an array arr = [a] that holds a reference to this object, what arr[0] actually stores is a reference to that object, not the actual object data.
I have many objects (20k+) such as a that I want to keep track of, probably creating an array similar to arr each second. As I want the memory allocation to be as efficient as possible, can I somehow tell the compiler that my array will only contain references to objects like a? I thought of using something like TypedArray, but I don't know what type the reference of a is, I guess I can't just use new UInt32Array() and actually store a at each index.
In languages like C++ you could have an array of pointers and you always know the size of a pointer (eg: 8 bytes on 64bit machines).
Is there any way to efficiently store references/pointers to objects in an Array or Object?
I think this answers my own questions. I can create an initial Array, add the elements that I want to it and then whenever I need a new array, just copy this one and update the elements. This way it doesn't matter what data type are the references, as I can directly allocate exactly the entire memory needed for the array.
Example in a pseudo-JavaScript:
var initialArray = [];
// push initial references into this array
// whenever I need a new array do:
var newArray = initialArray.slice();
// update references in the newArray
...
for i in newArray
newArray[i] = newRefi;
...
This way the newArray will be the correct size when created.
LE: Although this works in theory, it actually makes performance worse, probably because now creating the newArray now has to copy memory and do other crazy stuff instead of just allocating some memory.
I have an JavaScript object which is being pushed to a global object.
var storedElement = {
element: currentElement,
parentElement: parentElement,
elementChild: currentChild
}
storedElement is being pushed to a global array called.
pastLocations = []
I'm essentially trying to keep a history of the locations an element has been to. To do this I'm wanting to store these properties into the global array. If the same element already exists and has the same parent in the global then I dont want to push, but if the parent is different then push.
Is there a way I can put a unique key with item so I quickly and effectively get access to this element in the object. At the moment I currently have several for each loops to get the data from the object but this inst a practical approach. As Ideally I want 1 function to push to the global and to retrieve an element.
If I was to provide a unique keys for each object, how would I would know what key it is based of just knowing the element ?
In Javascript, an array [...] stores sequential values, preserving their order, and provides fast access if you know the index.
An object or dictionary {...} stores values along with a key, without preserving their order, and provides fast access if you know the key.
If you only need to store elements with distinct 'parent', you can use an object, using the parent as key. If you also need to browse them in order, your best bet is to use both an array and an object:
storedElements = []
storedByParent = {}
What you store in each depends on your application requirements. You may store a copy of the object:
newEl = {element: ..., parent: parentElement, ...}
storedElements.push(newEl)
storedByParent[parentElement] = newEl
Or you may store an index into the array:
storedElements.push(newEl)
storedByParent[parentElement] = storedElements.length - 1
Or you may store a simple boolean value, to just keep track of which parents you have seen:
storedElements.push(newEl)
storedByParent[parentElement] = true
This latter use of an object is usually known as 'set', because it's similar to the mathematical object: even if you call mySet[12] = true a hundred times, the set either contains the element 12, or it does not.
I have a javascript array of objects that are each created with 'new'. In the event of an error I would like to clear the whole array so that it would be GC'ed by the JS engine. To this end is it sufficient to just set the array variable to 'null' or do I need to splice all the elements from the array and set them to null before setting the array variable to 'null'?
The reason I am asking is that in Firefox I displayed (console.log) the array before assigning it to null and the displayed object (which is usually updated in the display I assume even later) still shows the elements of the array when I inspect it later, hence my doubt if the elements are actually being free'd or not.
To clear an array you can just set the length to zero:
var arr = [1,2,3,4,5];
console.log(arr);
arr.length=0;
console.log(arr);
Result:
[1, 2, 3, 4, 5]
[]
Edit:
Just found this on the topic: http://davidwalsh.name/empty-array
Looking at the comments it seems that just setting the variable to a new array is the simplest method:
arr = [];
According to the test results the memory is GC'd quicker than setting the length to 0. I would imagine this is to do with the allocations triggering the GC.
There is an interesting performance test on various methods here: http://jsperf.com/array-destroy
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)