andy sims
andy sims

Reputation: 3

Calling inner function in Nested Scopes in JavaScript

I'm learning JS and am wondering, is there a way to return the function bar() or buz() by without returning foo()? For example, if I wanted to return the function bar(); to get 2, could I do that? Would it be something like foo().bar(); ?

// Nested Scopes
function foo() {  // can only access itself
  var a = 1;

  function bar() {  // access to foo(), not buz()
    var b = 2;

    function buz() {   // access to bar() and foo()
      var c = 3;

      console.log(a, b, c);  // 1, 2, 3
    }
    buz();
    console.log(a, b);  // 1, 2
  }
  bar();
  console.log(a);  // 1
}
foo();  // 1

Upvotes: 0

Views: 62

Answers (3)

Sebastian Simon
Sebastian Simon

Reputation: 19485

You can do this, but it’s quite over-complicated.

The basic syntax is:

foo().bar().buz();

Where-ever you add another () after an existing one, it’ll print that level out. See the snippet for examples.

// Nested Scopes
function foo() { // can only access itself
  var a = 1;

  function bar() { // access to foo(), not buz()
    var b = 2;

    function buz() { // access to bar() and foo()
      var c = 3;

      return (function() {
        console.log(a, b, c);
      });
    }

    return (function() {
      var tmp = function() {
        console.log(a, b);
        return {
          buz: buz
        };
      };
      tmp.buz = buz;
      return tmp;
    })();
  }

  return (function() {
    var tmp = function() {
      console.log(a);
      return {
        bar: bar
      };
    };
    tmp.bar = bar;
    return tmp;
  })();
}


foo().bar().buz(); // (nothing)
foo().bar()().buz(); // 1, 2
foo()().bar()().buz(); // 1  // 1, 2
foo()().bar().buz()(); // 1  // 1, 2, 3
foo()().bar()().buz()(); // 1  // 1, 2  // 1, 2, 3

This kind of abuses the fact that you can assign properties to anything in JavaScript, including functions.

  • foo is a function that refers to the outer foo.
  • foo() is another function that refers to that inner tmp which has a bar property that refers to the inner bar function.
  • foo()() actually calls that inner tmp function but still leaves you with an object that has a bar property that again refers to the inner bar function.

This approach is basically the same for bar.

For buz, however, (something).buz() is just a function, without any extra properties and (something).buz()() doesn’t return anything, because that’s the final level.

Upvotes: 0

castletheperson
castletheperson

Reputation: 33476

Certainly. You can return an object at each stage which holds the function, or you can return the function itself. This utilizes what's called a closure.

function foo() {
  var a = 1;
  
  function bar() {
    var b = 2;
    
    function buz() {
      var c = 3;
      console.log(a, b, c);
    }
    
    console.log(a, b);
    return { buz: buz };
  }
  
  console.log(a);
  return { bar: bar };
}

foo().bar().buz();

Upvotes: 1

Chacliff
Chacliff

Reputation: 71

you do this more like setting a variable.

var foo = {

bar: function() { return 3; } }

console.log(foo.bar());

Upvotes: 0

Related Questions