Call function from string inside object? - javascript

I have a function name in a string:
var func = "doTest";
I need this function to be applied to the current instance ("this");
So I need it to call:
this.doTest();
How can I do this? I cannot go via window.
Thanks,
Wesley

Just use the construct of object[functionName]();, like so:
function Person() {};
Person.prototype.speak = function() { alert('ohai'); };
var john = new Person, action = 'speak';
john[action]();
Alternative style:
var Person = {
speak: function() { alert('ohai'); },
speakDelegate: function() { var action = 'speak'; this[action](); }
};
Person.speakDelegate();

this[func]();
No need to .call or .apply since context is held in the reference.
For example:
var obj = {
doTest: function(){ console.log(this); },
fn: function(){ var name='doTest'; this[name](); }
};
obj.fn(); // logs the object, proving this has the correct context.

Try the following
var funcObj = this["doTest"];
funcObj.apply(this);
What this does is grab the member named doTest from this. It then executes the function via apply and tells javascript to bind this as this within the function. I think the example is a bit less confusing if you consider the same code on a non-this value
var obj = {
doTest: function() {
console.log("doTest called");
}
};
var doTestFunc = obj["doTest"];
doTestFunc.apply(obj);
In this case the method doTest will be executed with the value obj as this

If you are using jquery you can just do:
$(this)[func]()

Related

Local vars javascript module pattern

How can I refer to a local variable inside a private function? For example, in the next code, in function myDisplay how can I get the object myObject of show function object and obtain id = 'B'?
var charge = (function($){
var open = function(){
var myObj = {
id: 'A'
};
};
var show = function(){
var myObj = {
id: 'B'
};
myDisplay();
};
function myDisplay(){
//Here, how to refer to var myObj of show function object?
}
return {
open: open,
show: show
};
})(jQuery);
The whole idea behind scoping is that you can't. myObj is private to the function stored in show.
Furthermore, in this particular example, myObj won't even exist unless a call to show() is actually in progress. Consider this point. It won't even exist during the myDisplay() call. (And two different calls to show() will each have different myObj instances.)
If you want the outer function and show to share data, move myObj out to the outer scope - the same scope that ret is in.
var charge = (function($) {
var myObjA = {
id: 'A'
};
var myObjB = {
id: 'B'
}
var open = function() {
};
var show = function() {
myDisplay();
};
function myDisplay() {
console.log(myObj);
//Here, how to refer to var myObj of show function object?
};
return {
open: open,
show: show
};
})(jQuery);
I recommended you use module pattern like that.
And, because the javascripts closure.
You can't read the myObj as you want it.
I provided you a solution hope you like it!

confusion, this-pointer and events in javascript

I have a javascript object which I would like to be able to handle some interactive features. It's a bit tricky to describe the scenario in a simple way so hopefully it'll not get all out of hand here.
my object looks something like
myobject = function() {
this.initialize = function() {
// HERE this = the myobject instance
var test = document.createElement('div');
test.onmousedown = this.mousedown;
}
this.mousedown = function(e) {
// HERE this = the calling div-element
}
}
So my problem is basically that this will not be an myobject instance when this.mousedown(e) is called, it will rather be the caller (if the terminology is correct?) in this case it is the div I created and put in a variable called test above.
I would like to have access to the instance on which the method is being run (as I believe that to be the mousedown method I created).
This far I have had some ideas which I have tried out:
create a data- attribute on the div containing the this object and operate on that.
sending the this pointer as an argument along with e to this.mousedown(e)
It's all I can think of now hope it makes sence.
You could create a copy when you first instantiate the object:
var myobject = function() {
var self = this;
this.initialize() {
// HERE this = the myobject instance
var test = document.createElement('div');
test.onmousedown = this.mousedown;
}
this.mousedown(e) {
// HERE this = the calling div-element
// use self instead of this
}
}
The simplest solution is to make a 'self' var that you refer to in the callback:
myobject = funciton() {
var self = this;
this.initialize() {
//use self to refer to myobject
self.mousedown(e);
}
this.mousedown(e) {
}
}

instantiating more than one object

in Javascript, I am creating an object like this:
var testObject = {
value: "this is my initial value",
setup: function() {
value: "foo"
}
};
Now, I would like to be able to instantiate this object, so I am trying this:
var myFirstObject = new testObject();
var mySecondObject = new testObject();
so that when I call .setup() it will change the value only for that referenced newly created object. How can I achieve this? This code does not seem to work.
You don't instantiate objects, you instantiate functions.
var testObject = function() {
this.value = "this is my initial value";
this.setup = function() {
this.value = "foo";
}
}
var myFirstObject = new testObject();
var mySecondObject = new testObject();
EDIT:
As per your comment, here's how you would bind to the DOM using functions on this object:
document.getElementById('idOfElem').addEventListener(
'click', myFirstObject.clickHandler);
Bear in mind that you won't have any guarantee that the click handler will be executed in the context of your object (i.e. in your click handler, this might not be your testObject instance). If your clickHandler intends to modify the object's instance variable in any way, it's better to ensure the context like so:
document.getElementById('el').addEventListener('click',
function() {
myObj.handleClick.apply(myObj, arguments);
});
You have numerous problems with your code. Firstly, you are trying to instantiate something, by calling a constructor function. Your testObject is not a function, so you'll cause a type error. You need to change testObject to be something along these lines:
var TestObject = function () {
this.value = "this is my initial value";
};
TestObject.prototype.setup = function () {
this.value = "foo";
};
Notice that I've used an uppercase T in that identifier... that's just best practice for a constructor function. Also notice how I've defined the setup method on the prototype. This is much more efficient than defining it as a property of the instance (with this.setup) since only one copy of the function needs to exist in memory.
Now that TestObject is a function it can be instantiated by calling it with the new operator:
var myFirstObject = new TestObject();
var mySecondObject = new TestObject();
When you call the setup method on an instance of TestObject, it will apply to that instance. In other words, the value of this inside the setup method will refer to the instance on which the method has been called:
myFirstObject.setup();
console.log(myFirstObject.value); // 'foo'
console.log(mySecondObject.value); // 'this is my initial value'
You have incorrectly defined your constructor. Try this:
function testObject() {
this.value = "this is my initial value";
this.setup = function() {
this.value = "foo"
}
};
You can then call new testObject().
The object notation your using is something you can compare with a static class.
Here is the code for what you're trying to achieve:
var testObject = function(val) {
this.value = "This is my initial value",
if (arguments[0]) {
this.value = val;
}
};
var first = new testObject(); //uses initial value
var second = new testObject("hi"); //value = hi
If you'd like to write classes using this notation take a look at this: http://ejohn.org/blog/simple-javascript-inheritance/
function yourObject(value, setup) {
return {
value: value,
setup: setup
};
}
var myFirstObject = new yourObject('a', function(){});
var mySecond = new yourObject('b', function(){});

Is it possible to append functions to a JS class that have access to the class's private variables?

I have an existing class I need to convert so I can append functions like my_class.prototype.my_funcs.afucntion = function(){ alert(private_var);} after the main object definition. What's the best/easiest method for converting an existing class to use this method? Currently I have a JavaScript object constructed like this:
var my_class = function (){
var private_var = '';
var private_int = 0
var private_var2 = '';
[...]
var private_func1 = function(id) {
return document.getElementById(id);
};
var private_func2 = function(id) {
alert(id);
};
return{
public_func1: function(){
},
my_funcs: {
do_this: function{
},
do_that: function(){
}
}
}
}();
Unfortunately, currently, I need to dynamically add functions and methods to this object with PHP based on user selected settings, there could be no functions added or 50. This is making adding features very complicated because to add a my_class.my_funcs.afunction(); function, I have to add a PHP call inside the JS file so it can access the private variables, and it just makes everything so messy.
I want to be able to use the prototype method so I can clean out all of the PHP calls inside the main JS file.
Try declaring your "Class" like this:
var MyClass = function () {
// Private variables and functions
var privateVar = '',
privateNum = 0,
privateVar2 = '',
privateFn = function (arg) {
return arg + privateNum;
};
// Public variables and functions
this.publicVar = '';
this.publicNum = 0;
this.publicVar2 = '';
this.publicFn = function () {
return 'foo';
};
this.publicObject = {
'property': 'value',
'fn': function () {
return 'bar';
}
};
};
You can augment this object by adding properties to its prototype (but they won't be accessible unless you create an instance of this class)
MyClass.prototype.aFunction = function (arg1, arg2) {
return arg1 + arg2 + this.publicNum;
// Has access to public members of the current instance
};
Helpful?
Edit: Make sure you create an instance of MyClass or nothing will work properly.
// Correct
var instance = new MyClass();
instance.publicFn(); //-> 'foo'
// Incorrect
MyClass.publicFn(); //-> TypeError
Okay, so the way you're constructing a class is different than what I usually do, but I was able to get the below working:
var my_class = function() {
var fn = function() {
this.do_this = function() { alert("do this"); }
this.do_that = function() { alert("do that"); }
}
return {
public_func1: function() { alert("public func1"); },
fn: fn,
my_funcs: new fn()
}
}
var instance = new my_class();
instance.fn.prototype.do_something_else = function() {
alert("doing something else");
}
instance.my_funcs.do_something_else();
As to what's happening [Edited]:
I changed your my_funcs object to a private method 'fn'
I passed a reference to it to a similar name 'fn' in the return object instance so that you can prototype it.
I made my_funcs an instance of the private member fn so that it will be able to execute all of the fn methods
Hope it helps, - Kevin
Maybe I'm missing what it is you're trying to do, but can't you just assign the prototype to the instance once you create it? So, first create your prototype object:
proto = function(){
var proto_func = function() {
return 'new proto func';
};
return {proto_func: proto_func};
}();
Then use it:
instance = new my_class();
instance.prototype = proto;
alert(instance.prototype.proto_func());

issues with 'this' when using within jquery code block

I want to use values of the calling object within the jquery code block, but 'this' is mapped to the jquery object and not eh caller! How to solve this PLEASE?
// class
myClass = function (){
// member object
this._localVars = {
_elementClass:'.elem-class',
_dots:null,
_dotStatus:null
};
// member function
this.func1 = function() {
$(this._elementClass).each(function(_index, _element){
// this._localVars._dots[_index] = _element; ... this line throws an error 'this._localVars' is undefined ... as 'this' is html element here and not an object of the calling class
});
};
};
Please suggest how can I use the 'this' inside the jquery code block to refer the variables/objects of the class and not HTML/jQuery.
Thanks
Try saving this object into a local variable
var myObject = this;
$(this._elementClass).each(function(_index, _element){
myObject._localVars._dots[_index] = _element;
});
You can use the jQuery.proxy method to set the value of this that you want.
You pass your function as the first parameter, and the current this as the second.
myClass = function (){
this._localVars = {
_elementClass:'.elem-class',
_dots:[],
_dotStatus:null
};
this.func1 = function() {
$(this._localVars._elementClass).each( $.proxy(function(_index, _element) {
this._localVars._dots[_index] = _element;
}, this));
};
};
var cl = new myClass();
cl.func1();
console.log(cl._localVars._dots);

Categories

Resources