By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,471 Members | 711 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,471 IT Pros & Developers. It's quick & easy.

How to call a method within an object via a parameter

Claus Mygind
100+
P: 571
I have an object with several methods within it.

I would like to call a specific method based on a variable.

Expand|Select|Wrap|Line Numbers
  1. function mapDataObject()
  2. {
  3.  this.a = function (){alert('a');};
  4.  this.b = function (){alert('b');};
  5.  this.c = function (){alert('c');};
  6.  this.d = function (){alert('d');};
  7.  this.e = function (){alert('e');};
  8. }
  9.  
  10. var mdo = new mapDataObject;
  11.  
I could use "if, else if" or a switch statement. But I would like to reduce it either one or just a few lines of code using a variable parameter. I am struggling with var function = window[functionstring], .call() and .apply()

The method to be executed will depend on the button clicked by the user.

Expand|Select|Wrap|Line Numbers
  1. function updatePage(button)
  2. {
  3.         var fn = window['mdo']+'.'+button.id;
  4.         fn();
  5. //        mdo.call(null, button.id);
  6. //        mdo.button.id();
  7. }
  8.  
  9.  


Can someone show me a simple example.

Yes I know I can just call mdo.a(); when a is clicked, but in this example other processing is occurring before arriving at updatePage();
Jan 31 '14 #1

✓ answered by Dormilich

but this does not work
Expand|Select|Wrap|Line Numbers
  1. var makeThisCall = "doThisMethod";
  2. mdo[makeThisCall](param1);
strange, it works for me (FF 26).

Share this Question
Share on Google+
10 Replies


Dormilich
Expert Mod 5K+
P: 8,639
The method to be executed will depend on the button clicked by the user.
wouldn’t it be the obvious choice then to attach the appropriate method to the click event?

alas, if that’s not possible, and you get the name of the method from the button itself (mind that this is somewhat unreliable), you can do
Expand|Select|Wrap|Line Numbers
  1. try {
  2.     mdo[button.name]();
  3. }
  4. catch(e) {
  5.     console.log("no such method name");
  6. }
Jan 31 '14 #2

Claus Mygind
100+
P: 571
Thank you for your response. I have had to put the current project on hold to resolve another issue that has crept up with sending out emails. I will get back to this when the other problem has been resolved.
Feb 3 '14 #3

Claus Mygind
100+
P: 571
The suggestion did not work. It simply returned an error "not a function"

So perhaps there is another option out there. Here is more detail about sequence of events.

1. I use a generic ajax call for all my calls. There may be many different types of calls from any individual page. They would include everything from submitting the whole form to smaller tasks like looking information for a small section of the page.

2. Any type of event can trigger this call. click, change etc.

3. The ajax object receives two pieces of information a form object (or pseudo form) and a data object. All information needed to make the ajax call and what to update on the callback are stored in these two objects.

4. my ajax object is stored in a generic library that I can attach to any page. The callback response is routed to a page specific object "updateRouter".

In the past I have simply used if - else if - etc. etc. to apply the specific update to the page on the client. There can be numerous response types, some require more coding than others but over all a very inefficient way of coding.

So, I took all the response types and placed them in an "upDate" object kind of a pseudo class where I can make a direct call to each update without having to pass over all the others in the process, as for example if I wanted to access the last of the "if else".

Now that just leaves me with the actual router which will call the specific update I need to apply. This gets back to my original question. I could use the same "if else" construct or use a switch statement. But what I really want is to make the call to the specific update method in my pseudo "update" class.

The following is an example of this
Expand|Select|Wrap|Line Numbers
  1. function mapDataClass()
  2. {
  3.   this.getjobLocation = function (callBack){
  4.     do some stuff....
  5.   }
  6.  
  7.   this.showAddrss = function (callBack){
  8.     do some stuff....
  9.   }
  10. }
  11. var mdo = new mapDataClass;
  12.  
  13. var updateRouter = function(which_method_To_Call, callBack_data){
  14.   //this would work
  15.   switch(which_method_To_Call)
  16.   {
  17.    case "getjobLocation":
  18.     mdo.getjobLocation(callBack_data);
  19.     break;
  20.    case "showAddrss":
  21.     mdo.showAddrss(callBack_data);
  22.     break;
  23.   }
  24. }
  25.  
  26.  
The question here is how to make the call directly without the switch. And as I understand it "eval()" is not a safe alternative as that leaves me open to injection.

Hopefully the explanation gives enough overview to generate some ideas?
Feb 3 '14 #4

Dormilich
Expert Mod 5K+
P: 8,639
The question here is how to make the call directly without the switch. And as I understand it "eval()" is not a safe alternative as that leaves me open to injection.
if there is no such method, eval() would fail nonetheless.

of course you can always use feature detection:
Expand|Select|Wrap|Line Numbers
  1. if (typeof obj[method_name] === "function") {
  2.     obj[method_name](parameters);
  3. }

The suggestion did not work. It simply returned an error "not a function"
well, I said it to be somewhat unreliable.


but I still don’t see why attaching the appropriate method to the resective event wouldn’t work.
Feb 3 '14 #5

Claus Mygind
100+
P: 571
eval() is a function. However it is still not a good option.
http://www.w3schools.com/jsref/jsref_eval.asp

As I tried to explain above. I do not advance to "update" until I have returned from my ajax call.

If I were to add it directly to the eventListner for the button, I would have to set a time out and not execute until the information was returned from the server.

I choose to branch after I get a response from the ajax call.

Here is a simplified example of the response branch.
Expand|Select|Wrap|Line Numbers
  1. request.onreadystatechange = function chkStateChange(){
  2.  if (request.readyState == 4) {
  3.    if (request.status == 200) {
  4.      goToUpdate(request.responseText, formObj);
  5.    }
  6.  }
  7.  
The method to call in the update has to be contained either in the responseText or in the formObj;
Feb 3 '14 #6

Claus Mygind
100+
P: 571
I can do this
Expand|Select|Wrap|Line Numbers
  1.  mdo['doThisMethod'](param1);
  2.  
but this does not work
Expand|Select|Wrap|Line Numbers
  1. var makeThisCall = "doThisMethod";
  2. mdo[makeThisCall](param1);
  3.  
Feb 3 '14 #7

Dormilich
Expert Mod 5K+
P: 8,639
but this does not work
Expand|Select|Wrap|Line Numbers
  1. var makeThisCall = "doThisMethod";
  2. mdo[makeThisCall](param1);
strange, it works for me (FF 26).
Feb 3 '14 #8

Rabbit
Expert Mod 10K+
P: 12,359
Are you referring to something like this?
Expand|Select|Wrap|Line Numbers
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script>
  5. function mapDataClass() 
  6.   this.a = function (callBack){ 
  7.     alert('a');
  8.   } 
  9.  
  10.   this.b = function (callBack){ 
  11.     alert('b');
  12.   } 
  13. var mdo = new mapDataClass;
  14.  
  15. function loadXMLDoc(funcToCall)
  16. {
  17. var xmlhttp;
  18. if (window.XMLHttpRequest)
  19.   {// code for IE7+, Firefox, Chrome, Opera, Safari
  20.   xmlhttp=new XMLHttpRequest();
  21.   }
  22. else
  23.   {// code for IE6, IE5
  24.   xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  25.   }
  26. xmlhttp.onreadystatechange=function(funcToCall)
  27.   {
  28.   if (xmlhttp.readyState==4 && xmlhttp.status==200)
  29.     {
  30.     funcToCall();
  31.     }
  32.   }
  33. xmlhttp.open("GET","ajax_info.txt",true);
  34. xmlhttp.send();
  35. }
  36. </script>
  37. </head>
  38. <body>
  39.  
  40. <div id="myDiv"><h2>Let AJAX change this text</h2></div>
  41. <button type="button" onclick="loadXMLDoc(mdo.a())">a</button>
  42. <button type="button" onclick="loadXMLDoc(mdo.b())">b</button>
  43.  
  44. </body>
  45. </html>
Feb 3 '14 #9

Dormilich
Expert Mod 5K+
P: 8,639
I had something like this in mind, though.

although some modifications are needed ...
Expand|Select|Wrap|Line Numbers
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script>
  5. // functions do not belong into an object constructor
  6. var mdo = { 
  7.   // the functions are called without parameter
  8.   // (at least in this scenario)
  9.   a : function (){ 
  10.     alert('a');
  11.   } 
  12.   b : function (){ 
  13.     alert('b');
  14.   } 
  15. };
  16.  
  17. function loadXMLDoc(funcToCall)
  18. {
  19. var xmlhttp;
  20. if (window.XMLHttpRequest)
  21.   {// code for IE7+, Firefox, Chrome, Opera, Safari
  22.   xmlhttp=new XMLHttpRequest();
  23.   }
  24. else
  25.   {// code for IE6, IE5
  26.   xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  27.   }
  28. // event handlers always pass the event (except IE before 8 (I think))
  29. // therefore you need the Closure
  30. xmlhttp.onreadystatechange=function()
  31.   {
  32.   if (xmlhttp.readyState==4 && xmlhttp.status==200)
  33.     {
  34.     funcToCall();
  35.     }
  36.   }
  37. xmlhttp.open("GET","ajax_info.txt",true);
  38. xmlhttp.send();
  39. }
  40. </script>
  41. </head>
  42. <body>
  43.  
  44. <div id="myDiv"><h2>Let AJAX change this text</h2></div>
  45. <!-- you have to pass the function itself, not its return value -->
  46. <button type="button" onclick="loadXMLDoc(mdo.a)">a</button>
  47. <button type="button" onclick="loadXMLDoc(mdo.b)">b</button>
  48.  
  49. </body>
  50. </html>
Feb 3 '14 #10

Claus Mygind
100+
P: 571
I appreciate the terrific input. I get the concept, but cannot implement it at this time because it changes the core of all my apps. So I have to stick to my current methods.

After a good night sleep, I was able to see that my problem came down to a typo in the code.

getjobLocation instead of getJobLocation. You were right Dormilich. This does work:
Expand|Select|Wrap|Line Numbers
  1.     var makeThisCall = "doThisMethod";
  2.     mdo[makeThisCall](param1);
  3.  
My router concept will work now. Thanks again Dormilich and Rabbit. It's nice to have a backup team like you guys.
Feb 4 '14 #11

Post your reply

Sign in to post your reply or Sign up for a free account.