8

I'm having a difficulty calling a function inside of another function when its name is in a variable:

var obj = {}

obj.f = function() {
  var inner = {
    a: function() {
      function b() {
        alert('got it!');
      }
      b(); // WORKS AS EXPECTED
      x = 'b';
      [x](); // DOESN'T WORK, NEITHER this[x]() window[x](), etc.
    }
  }
  inner.a();
}

obj.f();

I tried prefixing [x]() with different scope paths but so far w/o success. Searching existing answers did not turn up anything. It works with this[x]() if b() is placed directly inside object inner. I would like to keep b() as a function inside function a() because of variable scope in function a(), otherwise I would need to pass many parameters to b().

//// Re duplicate question: Quentin provided a more elegant answer in this thread imo.

5
  • try window[x].apply(this, [param1, param2]) apply Commented Jan 13, 2014 at 10:57
  • 1
    @RaraituL b will be scoped so you can't do this Commented Jan 13, 2014 at 10:58
  • @PaulS. The way x is defined, it will be created under window object Commented Jan 13, 2014 at 10:59
  • so you want call what function where? Commented Jan 13, 2014 at 10:59
  • @RaraituL — x will be but b won't. It is window['b'] that doesn't exist, not x. Commented Jan 13, 2014 at 11:01

6 Answers 6

19

There is no sensible way of accessing an arbitrary variable using a string matching the name of the variable. (For a very poor way to do so, see eval).

[x](); // DOESN'T WORK

You're trying to call an array as a function

NEITHER this[x]()

The function isn't a property of the inner object.

window[x](), etc.

Since it isn't a global, it isn't a property of the window object either.


If you need to call a function based on the value of a string variable, then organise your functions in an object and access them from that.

  function b() {
    alert('got it!');
  }
  var myFunctions = {
      b: b
  };
  x = 'b';
  myFunctions[x](); 
Sign up to request clarification or add additional context in comments.

1 Comment

var myFunctions = { b: b }; That did it!
3

Try this. Currently you are assigning string to variable x, instead of a function variable.

 x = b;
 x();

1 Comment

perhaps it could have worked if value b were assigned directly. it comes from a calculation. it's not real code in the example.
3

The problem is with your assignment

use x = b instead of x = 'b' to assign the function object as the latter just assigns the string into x.

Once you fix your assignment you can invoke the function as

x();
a.x();
a[x]();

etc.

1 Comment

you have to change the a[x](), to a["x"]();, unless x is a string variable with "x" value in it.
2

You should make array for the function and then access using name in your variable as follow:

var obj = {}

obj.f = function() {
  var inner = {
    a: function() {
      // set up the possible functions:
      var myFuncs = {
              b: function b() {alert('got it!');}
              };
      //b(); // WORKS AS EXPECTED --> commented this code
      x = 'b';
      myFuncs[x]();    
    }
  }
  inner.a();
}

1 Comment

@Gonki you need minimum changes in your code for this solution
1

The function declaration b will be captured in the closure of the anonymous function expression assigned as a.

  1. When var is used in a closure, there is no (available in JavaScript) Object which gets assigned a property similar to what happens with window in the Global Scope.
  2. Writing a function declaration effectively vars the name of the function.

If you really want to access a variable (i.e. b) by String, you will either need to create an Object which holds b similar to what you've done for a, or (and possibly dangerously) rely on an eval to convert "b" to b.

If you can't create the whole Object ahead-of-time, you can use this format

/* in (higher?) scope */
var fnRef = {};
// now when you
function b() {/* define as desired */}
// also keep a ref.
fnRef['b'] = b;
// fnRef['b']() will work **after this line**

Comments

1

let's say your code is like this:

//instead of x = 'b'
x = function(){}

then your solution could be like this:

var obj = {}

obj.f = function() {
  var inner = {
    a: function() {
      function b() {
        alert('got it!');
      }
      b(); // WORKS AS EXPECTED
      //you can define it as a variable
      var x = function(){};
      //and call it like this
      x();

      //or define it like this
      this[x] = function(){};
      //and call it like this
      this[x]();

      //but you are creating an array [x] which is not a function
      //and you are trying to call an array????
      [x](); // DOESN'T WORK, NEITHER this[x]() window[x](), etc.
    }
  }
  inner.a();
}

obj.f();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.