Dynamic function call to a class's function, using settimeout - javascript

I have a class like structure in javascript, Im attempting to invoke a sibling function using a passed in function name.
This is difficulty to explain so let me show you an example of what im trying to accomplish..
function windowFactory(){
this.init = function(functionName,args[]){
SetTimeout(functionName(args),2000)
}
this.func1 = function(var1){
alert(var1);
}
this.func2 = function(var1, var2){
alert(var1+var2);
}
}
var win1 = new windowFactory();
win1.init("func1","hello");
var win2 = new windowFactory();
win2.init("func2","world","!");
Please note that this is only a demo function, syntax errors / typos included.
Now i had this working using a dreaded Eval when it was outside the class...
eval(funcName+"('"+darray[1]+"','"+darray[2]+"')");
It just required it being outside the Class and passed in dummy values for parameters

Something like this should do the trick:
var windowFactory = function() {
var self = this;
this.init = function(functionName){
var args = Array.prototype.slice.call(arguments, 1);
setTimeout(function() {
self[functionName].apply(self, args);
}, 2000);
};
this.func1 = function(var1){
alert(var1);
};
this.func2 = function(var1, var2){
alert(var1+var2);
};
};
var win1 = new windowFactory();
win1.init("func1","hello");
var win2 = new windowFactory();
win2.init("func2","world","!");
Note the custom self reference var self = this;. This is used because when the timed out function is called, the this object will be window (at least in a web browser).
Another clarification: To address a specific object property in JavaScript you can do in the following ways:
object.property; // Or
object['property']; // When you have a string literal, like in your example

Related

Javascript prototype method "Cannot set property"

I'm always getting Cannot set property 'saySomething' of undefined but why?
Am I making a mistake somewhere?
var Person = new Object();
Person.prototype.saySomething = function ()
{
console.log("hello");
};
Person.saySomething();
Debugging tip: You get this ..of undefined errors when you try to access some property of undefined.
When you do new Object(), it creates a new empty object which doesn't have a prototype property.
I am not sure what exactly are we trying to achieve here but you can access prototype of function and use it.
var Person = function() {};
Person.prototype.saySomething = function() {
console.log("hello");
};
var aperson = new Person();
aperson.saySomething();
The prototype property exists on functions, not on instantiated objects.
var Person = new Object();
console.log(Person.prototype); // undefined
var Person2 = function () {}
console.log(Person2.prototype); // {}
This is useful because things put on the prototype of a function will be shared by all object instances created with that function (by using new).
var Person = function() {};
Person.prototype.saySomething = function() {
console.log("hello");
};
console.log(
new Person().saySomething === Person.prototype.saySomething // true. they are the same function
);
If all you want is to add a method to the person object, there's no need for a prototype:
var Person = {};
Person.saySomething = function() {
console.log("hello");
};
Person.saySomething();
You can even use object literal syntax:
var Person = {
saySomething: function() {
console.log("hello");
}
};
Person.saySomething();
i was trying out some code thought of posting it, might help others.
<script>
var MODULE = {};
MODULE = (function (my) {
my.anotherMethod = function () {
console.log("hello ");
};
my.newMethod = function(){
console.log("hi new method ");
}
return my;
}(MODULE));
MODULE.anotherMethod();
MODULE.newMethod();
</script>
And please not var MODULE ={}, if this is not initialized with {} then it give cannot set property.
I know i am late to the party but as you see there is no satisfying answer available to the question so i am providing my own.
In your case when you write
var Person = new Object();
you are creating an instance of Object type.
You can add a property using prototype property to the Object, not to the instance of Object.which you can use by the instance laterly.
so you can define like
Object.prototype.saySomething = function ()
{
console.log("hello");
};
now you can call it like this.
Person.saySomething();
You can check here.
var Person = function(name) {
this.canTalk = true;
this.name = name;
};
Person.prototype.greet = function() {
if (this.canTalk) {
console.log('Hi, I am ' + this.name);
}
};
bob = new Person('bob');
bob.greet();

Alternative to function.prototype.bind in callback

I am trying to avoid using function.prototype.bind in a project. I do not want to use a polyfill.
Considering the code below, is there a way to avoid
this.foo = new Obj2(this.callme.bind(this));
in the scenario below?:
function Obj1(){
this.value = 1;
this.foo = new Obj2(this.callme);
this.foo.doSomething();
}
Obj1.prototype.callme = function(){
console.log(this.value);
}
function Obj2(callback){
this.finished = callback;
}
Obj2.prototype.doSomething = function(){
// Do something here
this.finished();// obj2 will be in scope. Obj1.value will not be availble
}
var bar = new Obj1()
You can create a new closure to avoid using bind():
var self = this;
this.foo = new Obj2(function() { self.callme(); });
Not without writing additional/arguably messier code - this sort of thing is what bind is there for. As an alternative to the closure based approach in dsh's answer, you could pass in the context to use to the other object:
function Obj1(){
this.value = 1;
this.foo = new Obj2(this.callme, this);
this.foo.doSomething();
}
Obj1.prototype.callme = function(){
console.log(this.value);
}
function Obj2(callback, context){
this.finished = callback;
this.context = context;
}
Obj2.prototype.doSomething = function(){
// Do something here
this.finished.call(this.context);
}
var bar = new Obj1()
This is how certain standard functions such as Array.prototype.some work, where you can specify the object to use as this within the callback. You may want to code Obj2 so the context is optional, depending on your needs.

Object doesn't inherit parent object functions

I have some functions defined inside an object:
var functions = {
__construct: function(){
console.log(this);
this.prototype.__construct(); // <problem
}
};
I merge this object with another one that is a function (after I create a new instance of the function):
var plugin = function(){};
plugin.prototype.__construct = function(){
console.log('parent');
};
var i = new plugin();
i = $.extend({}, i, functions);
But after that when I try to call the __construct function:
i.__construct();
I get this error:
Uncaught TypeError: Cannot call method '__construct' of undefined
It's because this line:
this.prototype.__construct();
I tried to see if I can call the parent constructor function from the child constructor, but it appears that the object doesn't have a prototype? wtf?
Not sure what you're trying to do here but i does have a __construct function when using the code you provided:
var functions = {
__construct: function(){
console.log(this);
this.prototype.__construct(); // <problem
}
};
var plugin = function(){};
plugin.prototype.__construct = function(){
console.log('parent');
};
var i = new plugin();
i = $.extend({}, i, functions);
console.log(i.__construct===functions.__construct);//true
console.log(i.__construct===plugin.prototype.__construct);//false
Not sure what you think this.prototype is going to be, maybe this answer will clear up what prototype is used for (shared members) and what this means (instance specific). You can shadow shared members that are defined in the prototype further down the prototype chain or in an instance but that's not what you're doing here.
If you dynamically want to extend an instance created with a constructor function you can do something like this:
var functions = {
__construct: function(){
this.constructor.prototype.__construct.call(this);
}
};
var Plugin = function(){};
Plugin.prototype.__construct = function(){
console.log('parent');
};
var i = new Plugin();
i = $.extend(i,functions);
i.__construct();

JavaScript - Meaning of: var DndUpload = function (inputElem){};

Can I kindly ask for explanation:
What does the code below represent? Does it create a DndUpload Ojbect? Or, does it create a DndUpload() function? What I miss is the statement new normally present during JavaScript objects creation. Can I kindly ask for some explanation, as I am confused.
var DndUpload = function (inputElem)
{
this.input = inputElem;
this.dropZone = null;
this.isDragging = false;
this.init();
};
As far as I know this is the way to create object in Javascript:
var myObject = new function()
{
};
If you have any link with explanation, that would help. Thank you.
It's a worse way of writing this:
function DndUpload(inputElem)
{
this.input = inputElem;
this.dropZone = null;
this.isDragging = false;
this.init();
}
which is a function declaration. It does not create an instance of DndUpload. Technically, it does create an object – its name is DndUpload and it is an instance of Function. To create an instance of this "class:"
var instance = new DndUpload(document.getElementById('someInputId'));
var myObject = new function()
{
};
Defines an anonymous constructor function and then instantiates a new object using the anonymous constructor function. It could have been replaced with var myObject = {}.
var DndUpload = function (inputElem)
{
this.input = inputElem;
this.dropZone = null;
this.isDragging = false;
this.init();
};
Defines a constructor function (technically an anonymous constructor function assigned to a variable). You can then create objects of this "class" by invoking the constructor function with new:
var dndUploadObject = new DnDUpload(),
anotherUploadObject = new DnDUpload(); //2 unique DnDUpload objects
the code you have essentially creates a constructor for a "class" it's more or less a blueprint for an object.
It then puts that constructor into a variable called DndUpload
So you can now make an object with
var myObject = new DndUpload(input elem)

Carrying scope of "this" into inner functions

How can I extend the scope of this inward? I thought reassigning a higher scoped variable would do the trick... what am I doing wrong? http://jsfiddle.net/8bqXM/
function Player(configs) {
this.opts = {
playerID: "cSurf"
};
configs = $.extend(this.opts, configs);
var the = this;
this.init = function(){
var $player = $("#" + the.configs.playerID);
alert($player.attr("id"));
}
}
var cSurf = new Player();
$(document).ready(function(){
cSurf.init();
});
In your code, configs is not a public member of the Player object being created. You declared it without var so it's a global variable.
configs = $.extend(this.opts, configs);
should be:
this.configs = $.extend(this.opts, configs);
Then in your init() you can do the.configs.playerID.
Example: http://jsfiddle.net/rCuXa/
(Your jsFiddle also had MooTools loaded instead of jQuery. Check the menu on the left.)
EDIT:
By the way, since you're calling init() from the context of the new Player object, you really don't need to use the as the reference to this.
Inside init method, this refers to the Player that was created when you call it that way.
var $player = $("#" + this.configs.playerID);
Example: http://jsfiddle.net/rCuXa/1/
EDIT2: Additionally, if init() is always going to be called from the context of the Player instance you create, you may want to consider placing it on the prototype object of Player.
That way it will be shared among all instances instead of being recreated for each one:
Player.prototype.init = function(){
// ---------v----------"this" is the instance of Player
var $player = $("#" + this.configs.playerID);
alert($player.attr("id"));
}
Example: http://jsfiddle.net/rCuXa/2/
You just have a minor bug here. You're assigning the extend to configs, which is not on this, but then you reference it later via 'the' as if it is. This works:
function Player(configs) {
this.opts = {
playerID: "cSurf"
};
this.configs = $.extend(this.opts, configs);
var the = this;
this.init = function(){
var $player = $("#" + the.configs.playerID);
alert($player.attr("id"));
}
}
var cSurf = new Player();
cSurf.init();

Categories

Resources