How to maintain reference to an instance, when using the setTimeout callback? - javascript

How to maintain a reference to an instance, when using the setTimeout callback? E.G:
In my ViewModel (using Knockout)
var MyVM = function () {
this.myFunc = function () {
setTimeout("this.myCallback()", 2000);
};
this.myCallback = function() { this.myObservable(true); }
}
This fails.

You can add a private field :
var MyVM = function () {
var self = this;
this.myFunc = function () {
setTimeout(self.myCallback, 2000);
};
this.myCallback = function() { self.myObservable(true); }
}
var vm = new MyVM();
Have a look at the RP Niemeyer's answer.
I hope it helps.

Related

How can a function communicate with a prototype in an embeddable javascript widget?

I am trying to build an embeddable javascript widget. The following (example) is included in a script tag.
(function (window) {
function TestFunction(params) {
console.log("init");
this.someVal = "ThisVal";
}
TestFunction.prototype.protoFunc = function () {
return "Hello " + this.someVal;
};
function hello() {
return eval("TestFunction.protoFunc();");
}
}(window));
When I instantiate the widget as follows
let test = TestFunction({});
If I then type
test.protoFunc();
Hello ThisVal
will be printed. However if the hello function fires it throws an error saying that TestFunction.protoFunc is not a function. Is there a way that the hello() function can fire the TestFunction.prototype.protoFunc function?
I've updated the example a bit. The workflow is now object driven. If I misunderstood you please give me some more information.
(function (window) {
// Object instance
let instance = null;
// Class definition
var TestFunction = function (params) {
console.log("init");
this.options = params;
setTimeout(hello, 100); // triggering after initiation
}
// Class method
TestFunction.prototype.protoFunc = function () {
console.log("Hello " + this.options.name);
};
// the triggering function
function hello() {
return eval("instance.protoFunc()");
}
// initiate the instance
instance = new TestFunction({ name: 'Jon Doe' });
hello(); // trigger outside of class
}(window));
I've another example to show you how capsulating works.
var TestFunction = (function() {
function TestFunction(params) {
console.log('init');
this.options = params;
}
TestFunction.prototype.setName = function(name) {
this.options.name = name;
};
TestFunction.prototype.getName = function() {
return this.options.name;
};
TestFunction.prototype.protoFunc = function() {
console.log("Hello " + this.getName());
};
return TestFunction;
}());
var test = new TestFunction({
name: 'test'
});
test.protoFunc();
test.setName('Wuhu!');
test.protoFunc();

Calling one method from another in a Javascript class

When defining a class in Javascript, how can I call one method from another one?
exports.myClass = function () {
this.init = function() {
myInternalMethod();
}
this.myInternalMethod = function() {
//Do something
}
}
The code above gives me the following error when executing it:
ReferenceError: myInternalMethod is not defined
I also tried this.myInternalMethod and self.myInternalMethod, but both lead to errors.
What's the right way to do this?
I have created this fiddle http://jsfiddle.net/VFKkC/ Here you can call myInternalMedod()
var myClass = function () {
this.init = function() {
this.myInternalMethod();
}
this.myInternalMethod = function() {
console.log("internal");
}
}
var c = new myClass();
c.init();
this.myInternalMethod() does seem to work, though:
var exports = {};
exports.myClass = function () {
this.init = function() {
this.myInternalMethod();
}
this.myInternalMethod = function() {
//Do something
}
}
var x = new exports.myClass();
x.init();
Is it a private member?
exports.myClass = function () {
this.init = function() {
myInternalMethod();
}
function myInternalMethod() {
//Do something
}
}

Static member inside a function public inside namespace

How to make Static member inside a function public inside namespace
var myNamespace= new function()
{
this.myClass= function Page()
{
this.MyStaticVar = "myValue";
}
}
$("#block").html(myNamespace.myClass.MyStaticVar);
http://jsfiddle.net/DSs6r/97/
Please try it there...
The "namespace" shouldn’t be a function, and this isn’t right in either case.
var myNamespace = {
myClass: function Page() {
}
};
myNamespace.myClass.MyStaticVar = "myValue";
(Updated jsFiddle)
Like this:
var ns = {
Class: {
myStaticVar: 'myValue'
}
};
The main, only really, issue here was that you used a named function instead of an anonymous one (function Page()). Without the name, your code works just fine:
var myNamespace = new function()
{
this.myClass = new function()
{
this.MyStaticVar = "myValue";
};
};
Here is a jsfiddle showing the code working: http://jsfiddle.net/DSs6r/101/
More than likely, you were looking for a setup like this:
var myNamespace = new function()
{
var Page = function(){
var MyStaticVar = "myValue";
var MyDynamicVar = "";
function SetDynamicVar(val){
MyDynamicVar = val;
};
function GetDynamicVar(){
return MyDynamicVar;
}
return{
MyStaticVar: MyStaticVar,
SetDynamicVar: SetDynamicVar,
GetDynamicVar: GetDynamicVar
};
};
this.myClass = new Page();
};
Which would allow stuff like this:
myNamespace.myClass.SetDynamicVar("someValue")
$("#block").html(myNamespace.myClass.GetDynamicVar());
and:
$("#block").html(myNamespace.myClass.MyStaticVar);
Here is the working fiddle: http://jsfiddle.net/DSs6r/102/

How to reuse object constructor?

This is how I create objects from a hash of properties:
var object = new function (data) {
var self = this;
self.property = data.property;
self.anotherProperty = data.anotherProperty;
self.method = function () { return 'something'; }
self.update = function (newData) {
//what is here ?
//i could have written:
self.property = newData.property;
self.anotherProperty = newData.anotherProperty;
//but why not reuse the constructor?
}
};
I wonder how to reuse this function (constructor) to update an object from hash.
So that:
object.update(newData)
would update current object properties from newData hash the same way it is done in the constructor function.
By giving the constructor a name?
function MyNotReallyClass(data){
var self = this;
self.property = data.property;
self.method = function () { return 'something'; }
self.update = MyMyNotReallyClass;
};
you can can now call
var obj = new MyNotReallyClass(data);
var obj2 = new MyNotReallyClass(data);
and
obj.update(data);
i hope this helps.. i not 100% sure, because i'm learning too.. but yeah try it ;)
edit: after reading this comment of you: "But that would return a new instance, wouldn't it? Which i don't want."
i think you can write the Update function and call it in your constructor
var object = new function (data) {
var self = this;
self.update = function (newData) {
self.property = data.property;
self.method = function () { return 'something'; }
// and other things You want to do in constructor and update
}
self.update(data);
}
;

Passing javascript object property

How do you go about passing an objects properties in the follwoing situation:
ObjectTest = function()
{
this.var1= "3";
this.var2= "";
}
and the call
ObjectTest .prototype.allFriends = function() {
function bindEvents() {
//pass var1 here
}
}
Is there a way to pass the ObjectTest properties without passing them as properties of the bindEvents(). I'd prefer a global solution if at all possible
You use the same code in the prototype of allFriends as you used in the constructor:
ObjectTest = function()
{
this.var1= "3";
this.var2= "";
}
ObjectTest.prototype.allFriends = function() {
alert(this.var1);
}
It's the same: this.var1 - run this:
ObjectTest = function() {
this.var1 = 3;
this.var2 = "";
};
ObjectTest.prototype.allFriends = function() {
alert(this.var1);
};
x = new ObjectTest();
x.allFriends();
Or see this fiddle: http://jsfiddle.net/9XYZU/
ObjectTest.prototype.allFriends = function() {
do_smth_with(this.var1);
}
Beware, though, that you create a new ObjectTest by calling new ObjectTest(); without the new keyword it will not work.
EDIT: It will still work, because of the inner function will inherit the outer function's (allFriends) scope:
ObjectTest .prototype.allFriends = function() {
function bindEvents() {
console.log(this.var1);
}
}
If it still doesn't work for you, use a reference to the parent's this:
ObjectTest .prototype.allFriends = function() {
var parent = this;
function bindEvents() {
console.log(parent.var1);
}
}

Categories