Coming from C++ it is hard grained into my mind that everytime I call new I call delete. In JavaScript I find myself calling new occasionally in my code but (hoping) the garbage collection functionality in the browser will take care of the mess for me.
I don't like this - is there a delete method in JavaScript and is how I use it different from in C++?
Thanks.
var component = new Component();
component = null; // delete this at next garbage collection
Incidentally, the "new" keyword isn't really necessary in javascript, and has nothing (directly) to do with allocating memory. All "new" does is pass a new, empty object called "this" (this = {}) as a hidden argument to the function.
var MyClass = function(){
// fresh empty object "this" gets passed to function
// when you use the "new" keyword
this.method = function(){}
}
var myInstance = new MyClass();
Javascript can get kind of hairy with nested closures and multiple "this" variables floating around in different scopes. I prefer to do it this way:
var MyNoNewClass = function(){
// I find this more explicit and less confusing
var self = {}
self.method = function(){}
return self;
}
var myNoNewInstance = MyNoNewClass()
All JavaScript memory is referenced, but not in the traditional sense. Memory is referenced not by memory address but by a string. In this code:
var x = new someObj();
That object is referenced by the string "x" from that point forward. x is not a pointer to some memory on the heap at that point. If you assigned x a property then:
x.someProp = 42;
Then someProp is a string in memory referencing the value 42. Consequently that lets you use array notation to access it by it's string representation:
x["someProp"]++;
It's also why variables can hold any value as they don't have need of size.
Memory is collected in JavaScript, effectively, when no more strings (aka variables or property names) are referencing it. That object will be collected when x is assigned any other value. You could set it to null, undefined, or anything else and that memory will be collected.
That is, it will be collected when the browser or whatever JavaScript engine gets around to it.
Delete only removes properties from objects. From then on attempting to access that property will return undefined. For the most part, the following 2 lines of code are equivalent:
x["someProp"] = undefined;
delete x.someProp;
Edit: Ok, internally the two lines aren't the same. The delete operator will remove the "someProp" reference from memory, while setting it to undefined won't. I think. I can't find anything in the specs about setting a variable or property to undefined, but I don't think doing so does anything special.
The important thing to note is that you won't be able to delete properties that have a certain flag set, but you can set them to null or undefined (if they're not wrapped by a setter and even allow that to happen).
Taken outside of the context (the browser) the javascript is fully capable of reclaiming the memory through garbage collection. Going back to reality garbage collection in combination with DOM model can cause memory leaks.
Here is one article http://www.ibm.com/developerworks/web/library/wa-memleak/ you can find more details about it
To avoid memory leaks
Ensure you remove all event handlers, so if you add like a mouse down event handler ensure you remove it when you finish
if you add elements to the DOM, remove them when done
if you have an object that points to another object, remove the reference when the object is done with.
when you are finish with any object set it to null.
deletes just gonna remove a property from an object.
There is a delete. However, an actual need for it will be rare. It's not like C++ delete, though.
delete in JavaScript will remove a property from an object. Subsequent accesses of that property will return undefined. I assume it will be able to free any associated memory on subsequent garbage collects.
Don't use delete in JavaScript unless you are removing event handlers. Even then, we only do this because there is a memory leak associated with this practice in older versions of IE. Douglas Crockford explains this pretty well. In his case, he doesn't even use delete. He simply sets the values in question to null.
From the MDC:
The delete operator deletes a property of an object, or an element at a specified index in an array.
The delete operator in my opinion is only useful when you want to remove a property from an object. But since there might be other references to the property that it were referencing, it wont be really GCed. If you want something to be GCed, you need to remove all pointers pointing at it and also free the closures containing references to it (more info on the topic).
new creates objects from a constructor. delete removes properties from an object. These are two very different things.
You don't have to delete objects you created. The GC takes care of this.
delete o.fu is different from o.fu = undefined. Try this:
var o = {};
alert(o.hasOwnProperty('fu')); // -> false
o.fu = undefined;
alert(o.hasOwnProperty('fu')); // -> true
delete o.fu;
alert(o.hasOwnProperty('fu')); // -> false
There is a delete in Javascript, but trust me: it's way different than delete in something like C++. I recommend you don't even think about using it until you're more comfortable with Javascript.
Garbage collection works, though it doesn't defeat the problem of memory leaks.
The "new" keyword has nothing to do with memory. It's purpose is only to setup the prototype chain.
// C++
Foo* foo = new Foo(); // allocate and construct
// JS "sugar" using the new keyword
var foo = new Foo(); // allocate and construct
assert(foo instanceof Foo);
// JS constructing objects without "new"
var foo = Object.create(Foo.prototype); // allocate with prototype
Foo.call(foo); // construct
assert(foo instanceof Foo);
// construct Foo with missing prototype
var foo = {}; // allocate without prototype
Foo.call(foo); // construct without prototype
assert(!(foo instanceof Foo));
// so the corollary operations in JS are
foo = {};
foo = null;
// where-as this is an error (or most certainly not what you want)
delete foo;
// and this is how delete is used
foo = {bar: 42};
assert(foo.bar === 42);
delete foo.bar;
assert(foo.bar === undefined);
// but by deleting a property, you remove the reference to the object
foo = {bar: {baz: 31}};
delete foo.bar; // remove only reference to "bar" object
// JS GC will now take over
So no, you can't delete objects. But you can delete references to objects, which may trigger object deletion by the GC. But of course, local variables (and global) can't be deleted. They simply go out of scope, de-referencing any associated objects, and potentially freeing memory, but only if the object wasn't returned or is still referenced elsewhere.
It's important to realize that because JS doesn't support pointers, GC can be perfect. At any point, the GC can simply walk the entire set of objects "seen" from any in-scope function and guarantee it doesn't miss anything like cycles, etc.
As long as you use JS in a functional style and don't try to build global god objects which tie everything together, memory management should be a non-issue.
Related
I have some questions about my prototypal inheritance pattern that I am using for my app. First of all take a look at the pattern that I am using;
const myObjectProto = (function() {
const proto = Object.create( parentProto );
// private variables
let title = 'Some String';
// private functions
const addEmoticon = function() {
return title + ' ';
}
proto.getTitle = function() {
return addEmoticon();
}
return proto;
})();
And when I want to use it, I will use it like below:
const firstObject = Object.create( myObjectProto );
const secondObject = Object.create( myObjectProto );
// call a public function
firstObject.getTitle();
secondObject.getTitle();
My first question is this: assume that we are creating 100 objects from its corresponding proto; As far I know title is shared among them. That means if a function change it, it will be changed for all created objects. I am a little worried about the memory in this case. Do I use memory efficient with this pattern? Can someone clarify how Object.create treats with title?
My second question is about the memory leak; Let say that we want to set the firstObject to null;
firstObject = null;
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak. Am I right? If this is true, how can I fix it?
title is a local variable. It will exist as long as some code can access it. It will only exists once, as the IIFE only executes once, thus only one variable gets created. The function inside addEmoticon can access title, in other words it closures over it. As it is a local itself, it will also only exist as long as it can be accessed. It gets accessed inside the function stored inside proto.getTitle, which again closures over addEmoticon. proto.getTitle exists as long as proto can be accessed. As the value of proto gets stored inside the global variable const myObjectProto, it can always be accessed thus it will live forever (as well as every value that can be accessed through it, e.g. title).
Do I use memory efficient with this pattern?
Well, you allocate a few bytes once. Assuming that you have a few Megabytes available, thats not a lot.
As far I know title is shared among them
Yes.
Based on the fact that we have shared variables like title and even proto, I think it does nothing and I have memory leak.
You loose the reference to the instance stored in firstObject, thus making it viable for garbagge collection. That might free a few bytes. As the prototype is still available via secondObject and myObjectProto, it will continue living.
I have memory leak. Am I right?
A memory leak is a noticible amount of memory, that is still allocated although the values in it don't need to be used anymore. Under the assumption that you want to work with secondObject, and create new instances from myObjectProto, everything you've stored is still needed. Your code is perfectly fine.
Stylistically, I prefer this structure:
var Filter = function( category, value ){
this.category = category;
this.value = value;
// product is a JSON object
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
};
To this structure:
var Filter = function( category, value ){
this.category = category;
this.value = value;
};// var Filter = function(){...}
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
Functionally, are there any drawbacks to structuring my code this way? Will adding a prototypical method to a prototype object inside the constructor function's body (i.e. before the constructor function's expression statement closes) cause unexpected scoping issues?
I've used the first structure before with success, but I want to make sure I'm not setting myself for a debugging headache, or causing a fellow developer grief and aggravation due to bad coding practices.
Functionally, are there any drawbacks to structuring my code this way?
Will adding a prototypical method to a prototype object inside the
constructor function's body (i.e. before the constructor function's
expression statement closes) cause unexpected scoping issues?
Yes, there are drawbacks and unexpected scoping issues.
Assigning the prototype over and over to a locally defined function, both repeats that assignment and creates a new function object each time. The earlier assignments will be garbage collected since they are no longer referenced, but it's unnecessary work in both runtime execution of the constructor and in terms of garbage collection compared to the second code block.
There are unexpected scoping issues in some circumstances. See the Counter example at the end of my answer for an explicit example. If you refer to a local variable of the constructor from the prototype method, then your first example creates a potentially nasty bug in your code.
There are some other (more minor) differences. Your first scheme prohibits the use of the prototype outside the constructor as in:
Filter.prototype.checkProduct.apply(someFilterLikeObject, ...)
And, of course, if someone used:
Object.create(Filter.prototype)
without running the Filter constructor, that would also create a different result which is probably not as likely since it's reasonable to expect that something that uses the Filter prototype should run the Filter constructor in order to achieve expected results.
From a run-time performance point of view (performance of calling methods on the object), you would be better off with this:
var Filter = function( category, value ){
this.category = category;
this.value = value;
// product is a JSON object
this.checkProduct = function( product ){
// run some checks
return is_match;
}
};
There are some Javascript "experts" who claim that the memory savings of using the prototype is no longer needed (I watched a video lecture about that a few days ago) so it's time to start using the better performance of methods directly on the object rather than the prototype. I don't know if I'm ready to advocate that myself yet, but it was an interesting point to think about.
The biggest disadvantage of your first method I can think of is that it's really, really easy to make a nasty programming mistake. If you happen to think you can take advantage of the fact that the prototype method can now see local variables of the constructor, you will quickly shoot yourself in the foot as soon as you have more than one instance of your object. Imagine this circumstance:
var Counter = function(initialValue){
var value = initialValue;
// product is a JSON object
Counter.prototype.get = function() {
return value++;
}
};
var c1 = new Counter(0);
var c2 = new Counter(10);
console.log(c1.get()); // outputs 10, should output 0
Demonstration of the problem: http://jsfiddle.net/jfriend00/c7natr3d/
This is because, while it looks like the get method forms a closure and has access to the instance variables that are local variables of the constructor, it doesn't work that way in practice. Because all instances share the same prototype object, each new instance of the Counter object creates a new instance of the get function (which has access to the constructor local variables of the just created instance) and assigns it to the prototype, so now all instances have a get method that accesses the local variables of the constructor of the last instance created. It's a programming disaster as this is likely never what was intended and could easily be a head scratcher to figure out what went wrong and why.
While the other answers have focused on the things that are wrong with assigning to the prototype from inside the constructor, I'll focus on your first statement:
Stylistically, I prefer this structure
Probably you like the clean encapsulation that this notation offers - everything that belongs to the class is properly "scoped" to it by the {} block. (of course, the fallacy is that it is scoped to each run of the constructor function).
I suggest you take at the (revealing) module patterns that JavaScript offers. You get a much more explicit structure, standalone constructor declaration, class-scoped private variables, and everything properly encapsulated in a block:
var Filter = (function() {
function Filter(category, value) { // the constructor
this.category = category;
this.value = value;
}
// product is a JSON object
Filter.prototype.checkProduct = function(product) {
// run some checks
return is_match;
};
return Filter;
}());
The first example code kind of misses the purpose of the prototype. You will be recreating checkProduct method for each instance. While it will be defined only on the prototype, and will not consume memory for each instance, it will still take time.
If you wish to encapsulate the class you can check for the method's existence before stating the checkProduct method:
if(!Filter.prototype.checkProduct) {
Filter.prototype.checkProduct = function( product ){
// run some checks
return is_match;
}
}
There is one more thing you should consider. That anonymous function's closure now has access to all variables inside the constructor, so it might be tempting to access them, but that will lead you down a rabbit hole, as that function will only be privy to a single instance's closure. In your example it will be the last instance, and in my example it will be the first.
Biggest disadvantage of your code is closing possibility to override your methods.
If I write:
Filter.prototype.checkProduct = function( product ){
// run some checks
return different_result;
}
var a = new Filter(p1,p2);
a.checkProduct(product);
The result will be different than expected as original function will be called, not my.
In first example Filter prototype is not filled with functions until Filter is invoked at least once. What if somebody tries to inherit Filter prototypically? Using either nodejs'
function ExtendedFilter() {};
util.inherit(ExtendedFilter, Filter);
or Object.create:
function ExtendedFilter() {};
ExtendedFilter.prototype = Object.create(Filter.prototype);
always ends up with empty prototype in prototype chain if forgot or didn't know to invoke Filter first.
Just FYI, you cannot do this safely either:
function Constr(){
const privateVar = 'this var is private';
this.__proto__.getPrivateVar = function(){
return privateVar;
};
}
the reason is because Constr.prototype === this.__proto__, so you will have the same misbehavior.
If I do the following (in the global scope):
var myObject = {name: "Bob"};
I have a way to point to that object in memory (i.e. the string identifier "myObject)". I can open the console and type: myObject.name and the console will respond with:
"Bob"
Now, if I just type:
{name: "Jane"};
I'm creating that object somewhere and I'm guessing it goes on living in some scope. Is there any way I can find it? Does it exists under window somewhere in some generic store?
Edit: Some people are saying it will just get garbage collected.
So how about this example:
var MyObject = function(){
$("button").click(this.alert);
}
MyObject.prototype.alert = function(){
alert("I heard that!")
}
new MyObject();
It can't be garbage collected because its callback is bound to a DOM event. Where does the resulting object live and can it be accessed?
If there is no reference pointing to this object (that is you didn't assign it to any variable or to the value of any property), then there is no way to access it and in fact it's no living as the garbage collector can reclaim this memory immediately.
The short answer is no, the object isn't kept alive in memory somewhere you can't reach. Bit life is live: the truth is a bit more complicated, but not by much, if you grasp the basics.
Update:
In response to your update: you're right, in a way. The callback is a reference to MyObject.prototype.alert, which you accessed using this.alert, but that function object is being referenced by a constructors prototype, and can't be GC'ed anyway. The instance itself is not involved in the alert function itself, so it can be GC'ed safely.
Think of it like this:
MyConstructor.prototype.alert = 0x000123;//some memory address
||
\/
0x000123 = [object Function];
The function object itself isn't directly attached to anything, it floats there in memory, and is being referenced by the prototype. When you create an instance:
new MyConstructor().alert;
Is resolved as follows:
[new MyConstructor instance] allocated at e.g 0x000321
||
\\
\=>[alert] check for alert #instance -> not found
\\
\=> check prototype, yield 0x000123 <-- memory address, return this value
So upon executing the statement:
$("button").click(this.alert);
this.alert is an expression that is resolved to 0x000123. In other words, jQ's click method (function object) only receives the memory address of the alert function object. The instance, or indeed the constructor isn't involved at all. That's why this, or the call-context, can change depending on how and where a function is invoked. see here for more on ad-hoc context determination
I'll even do you one better:
/*assume your code is here*/
new MyConstructor().alert = function(){ alert('I am deaf');};
MyConstructor.prototype.alert = 'foo';
$('#button').click();
Guess what, the click event alert "I heard that" all the same, the prototype isn't even involved, let alone the instance.
If MyConstructor were to go out of scope, the click event will still work fine, because the GC still sees a reference to the alert function object that isn't out of scope yet. everything else is available for GC'ing, though...
The JS garbage collector (GC) is a flag-and-swipe GC. When the JS engine encounters your statement, it does allocate the memory required to store your object. When the next statement is reached, that object will probably still be in memory.
Every now and then, the GC X-checks all the objects it sees in memory, and tries to locate all references to that object that are still accessible. When it comes across the object literal that was just created in that statement, but no reference to was assigned, the object is flagged for garbage collection.
The next time the GC gets about its business of swiping flagged object, that object will be removed from memory.
Of course, this isn't entirely true for all engines. suppose your statement was written in an IIFE, that returned a function:
var foo = function()
{
{name: 'bar'};
return function()
{
return 'foobar';
};
}());
Some engines just keep the entire scope of the IIFE in memory, and only deallocate the memory for that scope when the return value of the IIFE goes out of scope (is flagged for GC). Other engines, like V8 last time I checked, will in fact flag those objects/vars of the outer scope that aren't referenced by its return value.
Though, come to think about it, it might not apply to this case, because the GC might even kick in even before the IIFE returns... But on the whole, that's just nit-picking.
There's also the question of logical OR's to consider:
var name = (mayNotExist || {name:'default'}).name;
In this case, if mayNotExist does exist, the object literal will never even be created, thanks to JS's short-circuit evaluation of expressions.
A couple of links on the matter:
Objects and functions in javascript
javascript - How to make this code work?
What makes my.class.js so fast?
Properties of Javascript function objects
From what I know, javascript, that is also based on ECMAscript the same as actionscript, does not really pass objects by reference. At least that's what I've read lately. For instance:
function doStuff(myObj){
myObj.name = 'groovy chicken';
myObj = null;
}
var newObj = new Object();
doStuff(newObj);
This is an example I found in a book 'Professional Javascript for web developers'. Although you are passing an object to the function, and adding the name property actually adds the property to your initial object, when you set to null, the object is destroyed in the local scope not in the global scope.
To me, this is still a bit confusing, since the myObj you have, is still pointing the same place as newObj and you can actully add or alter properties. The only difference is that you can not destroy it from the global scope.
So I'm wondering if the same also applies to actionscript, since from what I've read, actionscript 3 does actually pass objects by reference and I've not read anything stating the opposite.
Very few modern programming languages pass by reference (at least by default). In the twisted terminology of "pass by..", you're passing a reference by value. Here's how to think about it:
myObj and newObj are just variables, names for things.
The value of those variables are references to the object
When you call doStuff(), you're binding the name myObj to a new reference to your object (i.e. the reference itself was passed by value)
The reference points to a chunk of memory with some stuff in it, which is what lets you change the name inside of doStuff()
You can see that change by inspecting either variable because both variables contain references to the same object
myObj = null reassigns the variable to nothing, and in the process, it "destroys" the reference, but it doesn't destroy the object.
When the garbage collector notices there are no more references to an object, it will destroy that object
I'll try to help you understand the working of JavaScript's object:
when you say,
var newobj = new Object();
Here, newobj is only a name to the memory location allocated when you created an instance of Object.
When you pass newobj, it takes along the reference to the memory location. Now, myObj in the function is another name to the same memory location.
Adding a method 'name' adds it to the memory location and hence is available to both newobj and myobj.
when you set myobj to null, it removes that named reference and newobj still remains alive with the name property set.
But, I dont have an idea on how this works in actionscript.
Javascript copies objects by reference, rather than literally. For example:
var myObject = {};
var myCopy = myObject;
myObject.foo = "bar";
alert(myCopy.foo); //alerts "bar"
But I am really struggling to think of practical, real world reason for this other than giving developers a way to make code slightly more readable (as you can give different uses for the same object different names).
The most likely thing is I have missed the point, so can anyone tell me what that point is?
After writing:
var myObject = {};
There is an object out in memory somewhere that you can refer to by the name myObject. The following assignment:
var myCopy = myObject;
...says that myCopy now refers to that same object, wherever it may be. This is the same thing that happens when you give an argument to a function:
function somefunc(localName) {
// body
}
someFunc(myCopy);
Now there is a variable called localName that is local to someFunc that also refers to that same object out in memory.
This is the fundamental way in which we pass around references to an object, so that it can be referred to by different names, in different scopes.
We could copy the entire structure into a new location in memory. There was nothing stopping the designers from creating a language that did that. But it's less efficient -- think of deeply nested objects -- and generally not what you want to do. For example, if a function modified one property of an object, it would need to return the entire object for that change to persist outside of the function. And the caller would need to handle that return value, deciding whether the old object needs to be kept or if the newly created, slightly different copy can overwrite it.
Again, there's nothing wrong with this design direction in principle; it's just not how JavaScript was designed.
It depends; in your case it might be rather confusing since it doesn't serve a real purpose. However, for longer paths to the object it can be advantageous to store the object in a separate variable, because it requires less typing for each statement that uses the object, such as in this example:
var style = document.getElementById("foo").style;
style.color = "red";
style.font = "sans-serif";
// ...
My opinion (and it's nothing more than that) is that creating an object by reference (rather than copy) is generally more useful and what the user wants. If you pass an object as a param to a method, you're (almost always) interested in the object being worked on and altered by that method, rather than by working on a copy (and leaving the original untouched). Obviously there are circumstances where this is not true and it would be nice to have the option to choose, but I've can't recall ever finding myself wishing that I could just pass an object copy to a method, and am usually very grateful that the thing I'm working with is THE thing.