Javascript object lifecycle - javascript

I have a Javascript class like below:
var MYCLASS = function(elem, data, op) {
var options = {};
var loopForEver = function() {
console.log('I cant stop me');
setTimeout(function() {
loopForEver();
}, 1000);
}
this.init = function() {
loopForEver();
}
}
when I instantiate the class and call init function, then the loop starts and I get the text in my console every 1 second :
var ins = new MYCLASS();
ins.init();
Why when I set the instance to null, the thread does not stop? or any time I create a new instance and assign it to the previous instance name, it increases the calls.
in my production code, I do not have infinite loop, but I do have some business logic. do I need to be worried about performance when I create a new instance?

When you call setTimeout it is not bound by the function that called it. You need to add a property to object called something like timeOutID. As long as the function is still required being used by something like setTimeout it will remain in scope.
var MYCLASS = function(elem, data, op) {
var options = {};
var timeOutID = null;
var loopForEver = function() {
console.log('I cant stop me');
timeOutID = setTimeout(function() {
loopForEver();
}, 1000);
}
this.init = function() {
loopForEver();
}
this.stop = function () {
clearTimeout(timeOutID);
}
}

You have a memory leak.
In other words, memory leaks may occur when objects, which are now unreachable, are still kept in memory because they are being referenced somewhere else in the call stack.
Nullifying the instance doesn't clear from memory other references to that object. See this answer to "Can an object automatically delete itself in javascript once it has achieved its purpose?"
In fact, your setTimeout call is repeatedly creating a new execution context each with its own untouchable Activation object, which are unaffected by assigning the original instance to null.
An excerpt from "Understanding delete" (Perfection Kills by kangax) explains it this way:
When a function is executed, it is said that control enters
execution context…; that code might call a function, with its own execution context; that function could call another function, and so
on and so forth.
Even if function is calling itself recursively, a new execution
context is being entered with every invocation.
…when in Function code, a Variable object is … a so-called Activation
object. Activation object is created every time execution context for
Function code is entered.
Note that Activation object is an internal mechanism and is never
really accessible by program code.
If you want to nullify the instance, you should clean it up first by clearing the timed recursive call using .clearTimeout().

Related

What is better way to access this. Function.bind vs capturing variables

This is a basic question, but this impose an interesting question.
For instance,
var Foobar = function(){
this.baz = 100;
this.timer = null;
this.printLazy = function(){
this.timer = setTimeout(function(){
console.log(this.baz); //correctly bind this.
}.bind(this), 1000);
}
}
creates a traditional class that we can create instance and call printLazy as
var myBar = new Foobar();
myBar.printLazy();
Now in above code, printLazy method sets a timer and inside it, we access this.
Same thing can be achived using capturing as,
this.printLazy = function(){
var self = this; //capture this.
this.timer = setTimeout(function(){
console.log(self.baz); //correctly bind this.
}, 1000);
}
Is one of these methods are better than the other? (Considering efficiency or performance)
Can 2nd method can cause memory leaks, if its called lets say 1000 or more times in a quick succession where self would be referenced by other parts inside the function?
Is one of these methods are better than the other? (Considering efficiency or performance)
Not really. In your specific example, the version using bind creates an unnecessary function object (but JavaScript engines are very fast at doing that). But it also means that the function you're passing setTimeout doesn't close over anything, which is information the JavaScript engine might be able to use to optimize the context attached to it ("closure optimization").
But in modern environments, you'd probably use an arrow function in that situation rather than your self option:
this.printLazy = function(){
this.timer = setTimeout(() => {
console.log(this.baz);
}, 1000);
}
That will log this.baz as of when the timer fires. Another option, depending on what you need logged, would be setTimeout(console.log, 1000, this.baz). The difference is that this version will log the value this.baz has when the timer is set up, not as of when it fires. (It also relies on the fact that console.log, in most [but perhaps not all] environments, doesn't care what this is when you call it.) That's because setTimeout passes any extra arguments you give it to the function it calls when it calls it.
Can 2nd method can cause memory leaks, if its called lets say 1000 or more times in a quick succession where self would be referenced by other parts inside the function?
No. Memory leaks aren't caused by doing things quickly. They're caused by holding onto memory when you don't need it any more and not releasing it. What you're doing doesn't do that.
Had the same problem (in React) recently and found this article that shows several options. Below are 3 for your case, with the last one being the recommended option.
Option 1
Use arrow functions. But, this will still create a new function every time printLazy is called.
this.printLazy = function(){
this.timer = setTimeout(() => {
console.log(this.baz); //correctly bind this.
}, 1000);
}
Option 2
Create second function and bind it in the constructor, which still has performance drawbacks.
var Foobar = function(){
constructor() {
this.printLazyCallback = this.printLazyCallback.bind(this)
}
printLazyCallback() {
console.log(this.baz); //correctly bind this.
}
}
Option 3 (the one you should use)
Create second function as class prop arrow function
var Foobar = function(){
printLazyCallback = () => {
console.log(this.baz); //correctly bind this.
}
}

Newbie: Javascript constructor and scope-context issue

I'm confused as to what the problem is with context in a JS constructor. Within the ctor I have a function declared. Before the call to that function this is set to the context of the ctor. Inside the function the value of this is set to window. I don't understand why. In the HTML the ctor is called with 'new'.
function MyCtor() {
var myFunc = function() {
debugger; // #2
// code for myFunc
}
debugger; // #1
myFunc();
debugger; // #3
}
At debugger #1, this is set to MyCtor. At #2 this is window. And at #3 it is back to MyCtor.
I'm sure I'm missing something basic here, but I've read a lot on scope and context; obviously not enough.
The this object is one of the most annoyingly hard-to-understand concepts in Javascript. And that's quite a contest to win... First off, you have to understand that it will be specific to each function you call - the context in which you call myFunc won't set it how you want it. Here's one way you can do it:
function MyCtor() {
this.myFunc = function() {
debugger; // #2
// code for myFunc
}
debugger; // #1
this.myFunc();
debugger; // #3
}
Generally, there are only a few situations in which you can rely upon a function's this to be a particular value. All of them to my knowledge:
objectToBeThis.aFunction = function() { ... } // declare this function as
// an object property at any time -
objectToBeThis.aFunction();
Or, not used as often is:
aFunction.call(objectToBeThis, extraArgument1, extraArgument2);
When a named, but not "owned" function (ie, var functionName = function(), or function functionName()) is called, then it will have window as its this argument. This part I'm less sure of as a certainty, but I just wouldn't use this inside such a method.
As in the case of your code, there's also "new MyCtor" - in which a new object is created to be returned, and that object is set to this inside of the constructor method.

Javascript objects calling function from itself

I've been reading Game Design with HTML5 and JavaScript and it introduced me to objects. So after reading the book and working on the projects I decided to take this new found knowledge and integrate objects in my own projects. So here's my question can or should objects call their own functions? For example:
var someObject = {
start: function() {
check();
},
check: function() {
console.log("Check!");
}
};
someObject.start();
The book did show an example with a timer that does this:
var timer = {
start: function() {
var self = this;
window.setInterval(function(){self.tick();}, 1000);
},
tick: function() {
console.log('tick!');
}
};
In the example with timer object it makes a reference to self in order to call the internal function, so does this mean I should use self to call internal functions or is this the proper way to do this with objects? Or best practices? Thanks in advance.
var someObject = {
start: function() {
var self = this;
self.check();
},
check: function() {
console.log("Check!");
}
};
someObject.start();
JavaScript names are lexically scoped, so whenever a name (variable) is encountered in a script, the JavaScript runtime must search up the scopes from where the function was defined.
At the point of definition, this function:
start: function() {
check();
}
doesn't have access to any check function in its outer scope. Declaring self and binding it to this is a technique used to deal with the (somewhat interesting) intricacies of referring to the current object in JavaScript (because the example code uses window.setInterval).
To reference a function within the current object, it is enough to use this.
var someObject = {
start: function() {
this.check();
},
check: function() {
console.log("Check!");
}
};
It's javascript function context, each time you create a function, you create a new context (scope).
In setInterval() function you create a new scope, so this no longer refer as the same this above:
var self = this;
setInterval(function() {
self.tick();
}, 1000);
You can also manually bind the proper context of your function with bind() (so you don't need self anymore):
setInterval(function() {
this.tick();
}.bind(this), 1000);
More informations:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
http://joshuakehn.com/2011/10/20/Understanding-JavaScript-Context.html
The point of declaring and initializing a variable like "self" is to deal with the fact that the value of this is determined anew upon each function call. When you've got a function nested inside another function, and that inner function needs access to the value of this from the outer context, then this must be preserved in another variable — "self" in your case. (The name of that variable is unimportant of course.)
In your sample code:
var timer = {
start: function() {
var self = this;
window.setInterval(function(){self.tick();}, 1000);
},
tick: function() {
console.log('tick!');
}
};
that function passed in to setInterval() needs to use the value of this from the "start" function. When that interval timer function is called, however, this is set to something else (either the global context or null in "strict" mode). Thus, by saving the value of this in the context where that interval timer function is instantiated, its code can use it to access the timer object.
In your second example, declaring and initializing a "self" variable doesn't hurt anything, but it's unnecessary. Sometimes it's handy however, just to clarify the code, though of course a more meaningful name than "self" would be a good idea.
of course an object can and should call it's own functions, this is the only way to emulate OOP in javascript. I would say that the practice that the book is using, self = this is bad since this can just be used by itself, however in the first example it is used to preserve the value of this which would otherwise be the this of the function itself not the outer class

How to have an instance delete itself from within a prototype function is JavaScript

If I have a JavaScript constructor function, and I set a destroy method on its prototype. Is it possible to delete (or at least unset) the instance from the destroy method? Here's an example of what I'm trying to do.
Klass.prototype = {
init: function() {
// do stuff
},
destroy: function() {
// delete the instance
}
};
k = new Klass
k.destroy()
console.log(k) // I want this to be undefined
I understand that I can't simply do this = undefined from with the destroy method, but I thought I could get around that by using a timeout like so:
destroy: function() {
var self = this;
setTimeout( function() {
self = undefined
}, 0)
}
I thought the timeout function would have access to the instance via self from the closure (and it does), but that doesn't seem to work. If I console.log(self) from inside that function it shows up as undefined, but k in the global scope is still an instance of Klass.
Does anyone know how to make this work?
k is a reference that points out to an instance of Klass. when you call destroy as a method of Klass the this inside the function gets bound to the object you called a destroy method on. It now is another reference to that instance of Klass. The self that you close on in that little closure is yet another reference to that instance. When you set it to undefined you clear that reference, not the instance behind it. You can't really destroy that instance per se. You can forget about it (set all the references to undefined and you won't find it again) but that is as far as you can go.
That said, tell us what you want to accomplish with this and we'll be glad to help you find a solution.
Though deleting its own object instance is possible, it is very tacky. You might want to check out this article.
What you are trying to do is impossible. Even if you overwrite this it will not affect any variable holding a reference to that instance. And calling a function on it will still have the correct this.
The only thing you could do is setting a variable in your destroy function that will make any other function throw an exception when called. But that would be a bad idea since it would slow things down (ok, that's negligible) and you can just put in the docs of your class that it is not supposed to be used anymore after destroy() has been called.
This works, but it requires that you know what the name of variable to which the new Klass() is instantiated:
function Klass() {};
Klass.prototype = {
init: function() {
//
},
destroy: function() {
// Delete the variable that references the instance of the constructor.
delete window.k;
}
};
k = new Klass();
k.destroy();
console.log(k);
If the k variable is named anything else it doesn't work:
// Won't work.
u = new Klass();
u.destroy();
It also assumes that the local variable k is really in the global scope. If it were inside a function it would not work either. For instance:
// Won't work.
var fn = function() {
k = new Klass();
k.destroy();
};
Finally it assumes a browser environment for the window object.

What do JavaScript objects outlast and when are they destroyed?

I'm quite new to Javascript and I was just reading following article.
you can define an ajax connection
once, and reuse it multiple times, and
start and stop it later on. Here's an
example:
var myAjaxRequest = A.io.request('test.html', {
method: 'POST',
data: {
key1: 'value1'
}
});
Now later on, if I want to make that
same ajax call again, all I have to do
is call:
myAjaxRequest.start();
What if I had a very frequently used auction page and I wanted to use the myAjaxRequest connection for all actions a user does from his browser. What are the rules for lifetime of the myAjaxRequest instance ? I suppose it is destroyed on page refresh. But is it anything else that destroys it ? Let say that the object is created within YUI sandbox, but it doesn't matter.
Its a shame this was answered in comments because nobody gets closure (sorry, terrible pun). #Šime Vidas and #WaiLam deserve the credit but I will at least attempt to craft an answer:
While you have a reference to the object (though the variable myAjaxRequest) it will remain in memory until the document is unloaded. If you assign null to your variable (myAjaxRequest = null), and there are no other references to the object, then the garbage collector will reclaim the memory used to store it.
A reference can exist even if myAjaxRequest is a local variable within a function. The function can return a reference to the local variable, for example as a object property e.g:
function sandbox () {
var myAjaxRequest = A.io.request(/* constructor... */);
return {
myRequest: myAjaxRequest
};
}
var mySandbox = sandbox();
mySandbox.myRequest.start();
or it can return a reference through a closure (excellent explanation here), e.g:
function sandbox () {
var myAjaxRequest = A.io.request(/* constructor... */);
return {
getRequest: function () {
return myAjaxRequest;
}
};
}
var mySandbox = sandbox();
mySandbox.getRequest().start();
As long as you have a reference to your object it will not be garbage collected. You can safely call the start method until the page is unloaded.

Categories

Resources