0

I have string logo.cr.Button and function

logo.cr.Button = function(){
 //something
}

var strg = 'logo.cr.Button';
strg();

now somehow i have to make that string a function call

like strg(); but it is saying

strg is not a constructor

here

Waqar Haider
  • 929
  • 10
  • 33
  • edited my question a bit please check again – Waqar Haider Feb 11 '17 at 16:40
  • not working @thomas says not a function – Waqar Haider Feb 11 '17 at 16:46
  • 1
    Sounds like an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Why are you needing to do this in the first place? Provide more details about higher level problem you are trying to solve – charlietfl Feb 11 '17 at 16:47
  • @Waqar: I forgot about the name-spacing issues, my bad. – David Thomas Feb 11 '17 at 16:52
  • yeah thats that someone recomend @thomas ty – Waqar Haider Feb 11 '17 at 16:53
  • You really should avoid to use `eval` or `new Function`. Both will result in unexpected behavior if you need to use transpilars (e.g. when converting TypeScript to JavaScript) or if you want to use minification. While the linked duplicate is better then `eval` or `new Function`, it still suffers from the same problem. So you should tell why you need that, because there is most likely a better solution for that. – t.niese Feb 11 '17 at 17:06

4 Answers4

1

This won't work because JavaScript thinks you are using dot notation. When you write logo.cr.Button() JavaScript is looking for a function Button() within the object cr which is in the object logo.

I recommend changing the name to logoCrButton = function()...

Sean
  • 2,609
  • 1
  • 18
  • 34
1

You could use eval, but its not recommended. Secury issues are just one reason, because an user might exploit eval to execute different code that is not supposed to be executed. Within this question it is explained fully.

var logo={cr:{}};
logo.cr.Button = function(){
  console.log("something");
}

var string = "logo.cr.Button()";
eval(string);

If you can avoid eval then use a normal function call, an object or an array instead. For insteads Iterating through an array is much better and more stable compared to evaluating some parameters dynamically, as you can see here.

This second example does not use eval, but nevertheless you can call a certain function by using a string:

var obj={logo:{cr:{Button:function(){console.log("something");}}}};

var string = "logo.cr.Button";

function callFunctionByString(string,obj){
  var parts = string.split('.');
  parts.forEach(function(part){
    obj = obj[part];
  });
  obj();
}

callFunctionByString(string,obj);

Hope this helps.

Community
  • 1
  • 1
Blauharley
  • 4,186
  • 6
  • 28
  • 47
1

Use eval("logo.cr.Button")();

This will execute the function, of course if you have an object like:

var logo = {
    cr: {

    }
};
1

Generally when we write JavaScript functions the resulting function declaration looks like this:

function demo() {
  // function stuff here
}

You’re probably more than aware that “In JavaScript Functions are first-class Objects”. It’s a phrase that is spouted everywhere, and for good reason. It’s a very powerful idea that has worked to elevate JavaScript to where it is. We’re not going into the details of first-class objects here. All we care about is the fact that, in JavaScript, functions are objects. This means that the above function can also be declared by calling its Constructor:

var demo = new Function();

Now lets imagine we have a function with parameters and instructions:

function demo(name, age) {
  console.log('my name is ' + name);
  console.log('my age is ' + age);
}

and now to convert it to Constructor syntax:

var demo = new Function(
  "name,age",
  "console.log('my name is ' + name);" + 
  "console.log('my age is ' + age);"
);

This makes it pretty easy to see that these two functions are the same, they are just declared differently. The important difference is that one has easily accessible strings that we should be able to manipulate.

This applies to your function in a very similar way.

var strfunc = new Function ("", "logo.cr.Button()");

I can't seem to format this because I'm on mobile. But i will asap.

Waqar Haider
  • 929
  • 10
  • 33
zfrisch
  • 8,474
  • 1
  • 22
  • 34
  • 1
    Thanks that was very helpful – Waqar Haider Feb 11 '17 at 16:59
  • 1
    You should not use `eval` or `new Function` in such a way. In general it is a bad idea if `new Function` will access variables that are outside of the scope of this function, because it will result in unexpected behavior if you e.g. need to use a transpilar or a minification script. – t.niese Feb 11 '17 at 17:03
  • @t-niese I understand eval not being used, but new Function I've used with a transpiler and with a min script with no issues whatsoever. If you're worried about scope you could simply bind the appropriate context into the Function or pass it in as a parameter. I don't really see any grounds for the statement "you should not". I'd be happy if you could point out in more detail why you think that? – zfrisch Feb 11 '17 at 17:23
  • 1
    `eval` and `new Function` have the same problems. Both convert a string to code at runtime. As of that every transpiler, minification or linting script will normally ignore those strings when processing the code. If `logo.` is renamed by the transpiler or the minification script, then the code given as string would not be changed and will fail. So if you use `eval` or `new Function` then you should always make sure that you do not access variables that are defined outside of the evaluated code. Except if it is guaranteed to exist even after minification or transpile. – t.niese Feb 11 '17 at 17:37
  • I can see the concern. I suppose maybe I'm just a bit more lenient in my coding. I wouldn't argue that new Function should not be used more often than very, very rarely, but in terms of generating a function from a string, if you HAVE to, I find it to be the most appropriate and sensible solution. I will say that I honestly did not have any issues with a babel/js lint/min setup but perhaps I was just very lucky. That being said, I still disagree in that "you should not". If you can't find another way than this will work and there are situations where it, I think, is appropriate. – zfrisch Feb 11 '17 at 17:58
  • Sure if you have to evaluate code that is provided by a string then you need to use `eval`, `new Function` or similar. But in many cases (like this one) you dont need that, because there are either better ways to solve the actual problem or there is even a solution that would get ride of the problem at all. cases where evaluation of code is needed is to transpile code on the fly, for template engines that support both pre and on the fly compiled templates or rare cases where you need a global function without a closure. For all other situations there should be a solution without evaluation. – t.niese Feb 12 '17 at 05:48