11

I want to dynamically call a function from a string like "User.find". A script would call the function find() in the object User if the function exists. Here's what I tried:

 var User = {};
 User.find = function(){
     return 1;
 }

 var input = 'User.find';
 var some_data_array = {name: 'John Doe'};
 var method = input.toString().split('.');
 var nameObj = method[0].substring(0,1).toUpperCase() + method[0].substring(1);
 var methodToCall = method[1];

 nameObj.call(methodToCall, some_data_array);

But it always returns:

 nameObj.call(methodToCall, some_data_array);
 TypeError: Object User has no method 'call'

Any idea? I can't use window since it is a node.js problem, the script is not executed in the browser.

12
  • 1
    nameObj is a string, not a function? Commented Oct 12, 2014 at 18:06
  • when it comes to dynamic, try using eval. Commented Oct 12, 2014 at 18:06
  • That's why I'm asking here. I don't know how to call a function from a dynamic object. Commented Oct 12, 2014 at 18:06
  • 4
    @KingKing: No; don't use eval. Commented Oct 12, 2014 at 18:07
  • 3
    Yes I want to avoid using eval. Commented Oct 12, 2014 at 18:07

4 Answers 4

15

You're completely misunderstanding call().

call() lets you call a method with a different this.

You want to get as property by name:

object[methodName](arg1, arg, ...);
Sign up to request clarification or add additional context in comments.

7 Comments

Thank's for answering but it doesn't work for me : jsfiddle.net/74kmm6bp or maybe I didn't get how to use it.
This is not what the OP wants. At least the OP's problem is unclear now. He does not even have any right object here, as well as some reference to the method (just method name).
@Codel96: nameObj is a string. To get the global variable by that name, use the same syntax: window[nameObj].
I can't use window since the script is not executed in the browser but with node.js. I just edited with a more clear explanation of the problem.
@KingKing: That's because JSFiddle wraps the code in a function, so those are locals.
|
3

You actually can achieve this. You first would need to get the scope, where your namespace/function/object is defined.

For example, in your code I would assume its window.

So, a little modification of your code would produce the desired result:

var User = {};
User.find = function(x){
    alert(x);
}

 var input = 'User.find';
 var some_data_array = {name: 'John Doe'};
 var method = input.toString().split('.');
 var nameObj = global[method[0]];
 var methodToCall = method[1];

 nameObj[methodToCall](some_data_array.name);

Mark the use of global[]. This is where it starts.

[edited] * Modified code to use global instead of window as being used in nodejs.

6 Comments

The thing is I can't use window because it works server-side with node.
@Codel96: That is why I wrote - you need to get the scope and my example was using window scope. You probably would have a different scope (namely global). I will change the code.
Ok thank's for the answer. I'm gonna try that. I think I'll still go with SLaks answer because it's easier to manipulate data but it helped me ;).
The scope generally is where you define User and in majority of the cases it is given by this.
Notice that providing the client a possibility to call arbitrary methods on global and its descendants is as bad as using eval.
|
0

What you want to do is access the global object.

This should work:

var User = {};
User.find = function(){
    return 1;
}

var input = 'User.find';
var some_data_array = {name: 'John Doe'};
var method = input.toString().split('.');
var nameObj = method[0].substring(0,1).toUpperCase() +method[0].substring(1);
var methodToCall = method[1];

"use strict";
var global = (1,eval)("this");
alert(global[nameObj][methodToCall](some_data_array));

2 Comments

It won't work in jsfiddle, run in console. Edit: I'm assuming this is because of how fiddle runs the JS, and it's not declaring User object within the global scope.
Here's what I get: TypeError: Property 'connect' of object #<Object> is not a function
0

There are a couple of ways to get the desired result. In this case it is very simple to just use an anonymous function, as follows, passing in the string parameter contained in objName.name:

var f = function(oName){
  if (oName == 'John Doe') {
     return 1;
  }   
 };


 var objName = {name: 'John Doe'};
 
console.log( f( objName.name ) );

If the OP prefers to use an object's call method, the following code also will suffice:

var myObj = {
  myFunc: function() {
    if (this.name == 'John Doe') {
      return 1;
    }
  }
}

var objName = {
  name: 'John Doe'
};

console.log(myObj.myFunc.call(objName));

A couple of things to note. myObj calls its method myFunc() passing in the object parameter objName. The purpose of this in the method is to read the property name, possessing that ability because of being bound to the object objName.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.