As many of you are aware, the javascript delete keyword is a little tricky to use (see here). Is it possible to re-implement, or modify it? I have an object referenced multiple times and I want delete to remove all the references first. Like so:
var oj = new OrangeJuice();
var juice = oj;
var beverage = oj;
var allRightSunnyD = oj;
delete oj; //I want this to delete the actual object
I do not expect the garbage collector to find all of the references, lets say I know where the references are, i just want to re-implement delete to also get rid of juice, beverage and allRightSunnyD. I realize I could just implement a OrangeJuice.delete() function, but I wanted to know if there was a way to do it right. Like if javascript would call an onDelete() callback function prior to deleting objects.
delete is a keyword, so it should not be altered even if you can
delete is for deleting properties of objects, so you can not delete objects contained in single variables
look here how garbage collection in Javascript is explained: How does garbage collection work in JavaScript?
Related
I can understand the purpose of clone() method when appending a copy element like this:
$aObject = $('.className').clone();
$aObject.removeAttr('id');
$('#add-line').click(function() {
$('#container').append( $aObject.clone());
});
But what I don't understand is, if I get rid of the clone method, just using
$('#container').append( $aObject);
I should still be able to add multiple same object to the container, but it seems like I can only add the aObject once? can't we add same object many times on purpose just like an array of same objects?
When you assign an object to a variable in JavaScript, you aren’t actually assigning the object value stored in memory – rather a reference that points to the object’s location in memory.
So, when you declare $aObject, you have now stored a reference to a particular object. When you append it, it behaves as you would expect, appending the object that you are referencing. When you try to do the same thing again, it is referring to the same object that now already exists in the DOM and simply takes that object and re-appends it (what Scott Marcus meant when he said it acts as move).
If you clone it first, then you are referencing an entirely different object, which can be appended in addition to any objects you've already appended.
So I learned a bit about the hidden class concept in v8. It is said that you should declare all properties in the constructor (if using prototype based "pseudo classes") and that you should not delete them or add new ones outside of the constructor. So far, so good.
1) But what about properties where you know the type (that you also shouldn't change) but not the (initial) value?
For example, is it sufficient to do something like this:
var Foo = function () {
this.myString;
this.myNumber;
}
... and assign concrete values later on, or would it be better to assign a "bogus" value upfront, like this:
var Foo = function () {
this.myString = "";
this.myNumber = 0;
}
2) Another thing is with objects. Sometimes I just know that an object wont have a fixed structure, but I want to use it as a hash map. Is there any (non verbose) way to tell the compiler I want to use it this way, so that it isn't optimized (and deopted later on)?
Update
Thanks for your input! So after reading your comments (and more on the internet) I consider these points as "best practices":
Do define all properties of a class in the constructor (also applies for defining simple objects)
You have to assign something to these properties, even if thats just null or undefined - just stating this.myString; is apparently not enough
Because you have to assign something anyways I think assigning a "bogus" value in case you can't assign the final value immediatly cannot hurt, so that the compiler does "know" ASAP what type you want to use. So, for example this.myString = "";
In case of objects, do assign the whole structure if you know it beforehand, and again assign dummy values to it's properties if you don't know them immediatly. Otherwise, for example when intending to use the Object as a hashmap, just do: this.myObject = {};. Think its not worth indicating to the compiler that this should be a hashmap. If you really want to do this, I found a trick that assigns a dummy property to this object and deletes it immediatly afterwards. But I won't do this.
As for smaller Arrays it's apparently recommended (reference: https://www.youtube.com/watch?v=UJPdhx5zTaw&feature=youtu.be&t=25m40s) to preallocate them especially if you know the final size, so for example: this.myArray = new Array(4);
Don't delete properties later on! Just null them if needed
Don't change types after assigning! This will add another hidden class and hurt performance. I think thats best practice anyways. The only case where I have different types is for certain function arguments anyways. In that case I usually convert them to the same target type.
Same applies if you keep adding additional properties later on.
That being said, I also think doing this will lean to cleaner and more organized code, and also helps with documenting.
Yeah, so one little thing I am unsure remains: What if I define properties in a function (for example a kind of configure() method) called within the constructor?
Re 1): Just reading properties, like in your first snippet, does not do anything to the object. You need to assign them to create the properties.
But for object properties it doesn't actually matter much what values you initialise them with, as long as you do initialise them. Even undefined should be fine.
The concrete values are much more relevant for arrays, where you want to make sure to create them with the right elements (and without any holes!) because the VM tries to keep them homogeneous. In particular, never use the Array constructor, because that creates just holes.
Re 2): There are ways to trick the VM into using a dictionary representation, but they depend on VM and version and aren't really reliable. In general, it is best to avoid using objects as maps altogether. Since ES6, there is a proper Map class.
I would like to know the correct way to completely dereference a JavaScript Object from memory. To ensure it's deletion without it dangling in memory, and that the garbage collector removes the object.
When I looked and this question Deleting Objects in JavaScript. It was explained that if you delete all the references of object, the GC will remove it from memory. I want to know how do I go about removing references from an object that has both methods and properties.
Suppose you have and object that was created by using function, and the object has both methods and properties. Say it looks something like this:
function myObject(x, y) {
this.x = x;
this.y = y;
this.myMethod = function() {
// method code
}
}
var myInstance = new myObject(24, 42) // How to remove this completely?
Note: This is an example, I understand you can use prototype for methods.
I know I can't just say delete myInstance. So in this case to completely delete the object will I need to call delete on all it's properties, and then call delete on the instance, like so?
delete myInstance.x;
delete myInstance.y;
delete myInstance; // I'm not sure if this is necessary.
Would this work? Or do I need to also delete it's methods (and if so how)?
Or perhaps there is a better and simpler way to do this?
Javascript is a garbage collected language. It will clean up an object ONLY when there is no other code that has a reference to it. Those other references need to either go out of scope (and not be held by a closure) or you can set those other variables to something else so they don't point at your object. When there are no other variables with a reference to your object, it will be automatically taken care of by the garbage collector, including any properties it has (assuming none of those properties are themselves objects that something has a reference to - but even then the host object would be cleaned up and only the object in the property would continue to live on).
You cannot delete an object any other way in Javascript.
So, to remove the object created by this:
var myInstance = new myObject(24, 42) // How to remove this completely?
Just clear myInstance like this:
myInstance = null;
You don't need to manually delete the properties from myInstance at all. If nobody has a reference to the mother object and none of the properties are objects that someone has a reference to, then the garbage collector will just clean everything up for you.
The delete operator is primarily for removing properties from an object when you want the mother object to remain (e.g. when you just want to remove a property).
What is a memory efficient way to link two objects? If you store objects using two arrays with corresponding index values the object won't be released from memory.
The implementation should look like the following.
var obj ={};
var linkedobj = getLinkedObject(obj);
var obj2 ={}
var linkedobj2 = getLinkedObject(obj2);
Objects are general containers
If all you want to do is associate one object with another one, then why not have them point to one another?
var obj = {};
var obj2 = {};
obj.linkedObject = obj2;
obj2.linkedObject = obj;
This would a normal thing to do, and doesn't have bad implications on memory.
Releasing memory
If you are asking about holding a table full of object references, you are correct that the object will not disappear until all of the live references to it are gone. Javascript has a garbage collector, and as long as your table or array has a good reference, it will be backed by memory for you. If you give an object to a table and then want it to be deleted from memory entirely, you can simply remove it from your table also. You could also just remove the table, assuming it doesn't need to hold anything else.
If you are determined to have a getLinkedObject function return an object for another object, you can still allow the objects to each hold the associate reference.
function getLinkedObject(anObject) {
return anObject.linkedObject;
}
This would probably be accompanied by a counterpart:
function linkObjects(anObject, anotherObject) {
anObject.linkedObject = anotherObject;
anotherObject.linkedObject = anObject;
}
Doing this allows you to worry a little less about memory management, which in Javascript (a high-level, dynamic environment with a garbage collector) is typically appropriate.
Unless you use keparo's answer, which from your follow-up comment sounds like not an option, what you're asking for is basically impossible. Because, since you can't augment the original object, you need some method of storing a reference to it. But (since JavaScript has no concept of weak references) this will always prevent it from being garbage collected, contradicting your requirements statement.
I used to store variables separately, for example, if I have an old element I would save it in a variable called "ele_old", and then later if I have a new element I would save that in a variable called "ele_new". However, it just occurred to me that I can save the 2 variables in 1 array variable, so I could do something like this:
eles_arr['old'] = //old element;
eles_arr['new'] = //new element;
this way would allow me to put variables of the same type into the same array for better organization, e.g. elements together in 1 array, and then ids together in another array.
The problem is I am quite new to javascript (and any other programming languages, for that matter), so I'm wondering if this is an inferior way than just keeping each variable separate. Will doing this cause any problems? for example, poor runtime performance?
Thanks!
What you're doing is setting properties on the eles_arr object. It's akin to saying:
eles_arr.oldEl = //old element
eles_arr.newEl = //new element
It's not storing them in an array, so it's similar to having the variables separated -- they're just grouped in the eles_arr object. To put them in an array you'd do:
eles_arr.push(oldEl);
eles_arr.push(newEl);
That being said I wouldn't put these two variables in an array. I would keep them separated to increase readability. It might make sense to you to have the values in the same array, and you may remember their positioning. Other developers may not though, which could lead to problems in the future.
Finally, having an array of two values for 'old' and 'new' will in no way affect performance in your case, but I still would not recommend using an array for readability's sake.
Update
I changed the variables from 'old' and 'new' to 'oldEl' and 'newEl' to reflect Šime's comment on the reserved keyword 'new'.
You can use an object to create a namespace / module, and so reduce the number of global / local variables:
var eles = {};
eles.foo = document.getElementById("foo");
eles.bar = document.getElementById("bar");
But that probably makes sense only if you have like 20 or more elements and you need them in various event handlers / functions. In that case, it makes sense to create the eles namespace and populate it with all your element references.