Javascript dynamically invoke object method from string - javascript

Can I dynamically call an object method having the method name as a string? I would imagine it like this:
var FooClass = function() {
this.smile = function() {};
}
var method = "smile";
var foo = new FooClass();
// I want to run smile on the foo instance.
foo.{mysterious code}(); // being executed as foo.smile();

if the name of the property is stored in a variable, use []
foo[method]();

Properties of objects can be accessed through the array notation:
var method = "smile";
foo[method](); // will execute the method "smile"

When we call a function inside an object, we need provide the name of the function as a String.
var obj = {talk: function(){ console.log('Hi') }};
obj['talk'](); //prints "Hi"
obj[talk]()// Does not work

method can be call with eval
eval("foo." + method + "()");
might not be very good way.

I would like to leave an example here for this. For example; i want to call a dynamically check method while submitting the form.
<form data-before-submit="MyObject.myMethod">
<button type="submit">Submit</button>
</form>
$('form').on('submit', function(e){
var beforeSubmit = $(this).attr('data-before-submit');
if( beforeSubmit ){
params = beforeSubmit.split(".");
objectName = params[0];
methodName = params[1];
result = window[objectName][methodName]($(this));
if( result !== true ){
e.preventDefault();
}
}
});
var MyObject = {
myMethod = function(form){
console.log('worked');
return true;
}
};

Related

Javascript substitution of object's method

I have a problems with object's manipulation in javascript
My code:
SearchField = function(){
this.Init = function()
{
this.input = this.view.getElementsByTagName("input");
this.input[0].onkeyup = this.UpdateEvent2;
self = this;
}
this.UpdateEvent = function(){
this.OnUpdate();
}
this.UpdateEvent2 = this.UpdateEvent.bind(this);
this.OnUpdate = function(){
alert("Hello world from direct object");
};
}
Some explanations for this code: I used a bind method to pass as argument the Object itself, instead of event object.
So, I have a function OnUpdate with some code inside.
After Instantiation of my Object in some other part of my code I have some other lines:
...
targetController.prototype[targetMethodName] = function(targetController){
alert("core");
return selfController[selfMethodName](targetController);
}
...
Where targetController is a reference to my object and targetMethodeName is a method OnUpdate(). Then I try to assign a new function to this method, in other words, try to Substitute the original method OnUpdate with another method from another object. (It dosen't metter 'couse it dosen't work in anyway, even invoking alert("core").)
So, when I try to call this method like this: MyObject.OnUpdate() - result is an alert window with "Hello world from direct object".
The first quastion is how can I substitute this method by another one?
But, there's some interesting behavior if I assign this method directly to the event handler like this:
SearchField = function(){
this.Init = function()
{
this.input = this.view.getElementsByTagName("input");
this.input[0].onkeyup = this.OnUpdate;
self = this;
}
this.OnUpdate = function(){
alert("Hello world from direct object");
};
}
In this case everything works perfectly, so I have an alert window with "core" inside and another method from another object invoked with right arguments...
So, the second quastion is ... what's wrong in the first variant??? I don't want to assign my method directly to the event handler! I whant to call this method in any part of my code! How to do this?
P.S. As you can see I tried to do this with self instead of this and so on... Nothing helps!
Looks like you are trying to overwrite a keyup function after the class is created?
One way you could do this is to init with the original function, then overwrite it:
<div id="field">
<input type="text" value="search1" />
</div>
<div id="field2">
<input type="text" value="search2" />
</div>
<script>
var SearchField = function (id) {
this.init = function () {
var me = this;
this.el = document.getElementById(id);
this.input = this.el.getElementsByTagName('input');
this.input[0].addEventListener('keyup', function (e) {
me.onKeyUp(e);
});
self = this;
}
this.onKeyUp = function (e) {
console.log('onKeyUp');
};
this.init();
};
var search1 = new SearchField('field');
var search2 = new SearchField('field2');
// overwrite the key up function
search2.onKeyUp = function(e) {
console.log('onKeyUp2');
};
</script>
http://jsfiddle.net/kmturley/CHK96/

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(){});

Calling one prototype method inside another in javascript

var Ob = function(){
}
Ob.prototype.add = function(){
inc()
}
Ob.prototype.inc = function(){
alert(' Inc called ');
}
window.onload = function(){
var o = new Ob();
o.add();
}
I would like to call something like this,how can i call, ofcourse i put inc as inner function to add I can do that but without having the inner function. how do i do that ?
It's easy:
Ob.prototype.add = function(){
this.inc()
}
Ob.prototype.inc = function(){
alert(' Inc called ');
}
When you create the instance of Ob properties from prototype are copied to the object. If you want to access the methods of instance from within its another method you could use this.

Call function from string inside object?

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]()

jQuery type function as a variable

can I create a variable that is a function of this type:
jQuery.fn.appendValueToTextArea = function(txt){
return this.each(function(){
this.value += txt;
});
};
?
I tried putting a var in front of it but I get a error.
If you want to call a method on an element like you wrote in the comment, you definitely have to extend jQuery.func.
Maybe you just want to store the name in a variable?
var name = 'appendValueToTextArea';
element[name]('text');
The only other way is to store a reference to the function and use .call() or .apply():
var func = jQuery.fn.appendValueToTextArea = function(txt) {
// ...
};
func.call(element, 'text');
Or (as I am not sure what you really want) you can assign the function to a variable first and then assign it to jQuery.fn.appendValueToTextArea:
var func = function(txt) {
// ...
};
jQuery.fn.appendValueToTextArea = func;
What happens if you define the variable after the function has been defined?
i.e.
jQuery.fn.appendValueToTextArea = function(txt){
return this.each(function(){
this.value += txt;
});
};
var fn = jQuery.fn.appendValueToTextArea;
jQuery.fn.appendValueToTextArea = function(txt){
return this.each(function(){
this.value += txt;
});
};
//This would put the function above in a variable.
//However, I'm not exactly sure what this gains you
var myfunction = jQuery.fn.appendValueToTextArea;

Categories

Resources