0

If I create a callback within a function, can I get that callback to access the local variables within that function?

Obj.prototype.outerFunc = function() 
{
    var x = 0;
    var callback = this.innerFunc;
    callback();
}

Obj.prototype.innerFunc = function()
{
    x++;
}

x naturally is not within the scope of innerFunc and will produce an error if called by itself. But if I call it from outerFunc can I extend innerFunc's scope in order to access x?

Edit: Should've mentioned that I don't want to pass arguments into the function or make x and instance of Obj. I'm more looking to treat innerFunc as though it was declared locally in outerFunc. Similar to what can be done below:

Obj.prototype.outerFunc = function()
{
    var x = 0;
    var callback = function() {
        x++;
    }
    callback(); // works
}
1
  • 1
    The only way would be if outerFunc put x in a shared scope. The global scope is shared between all functions. But there isn't no way to directly influence the scope of the callee. Basically what you are after is called dynamic scope. JavaScript and most languages have lexical scope. Commented Mar 25, 2017 at 16:07

5 Answers 5

1

Yes: this is exactly what function parameters are for. They allow you to pass a value from one scope into another.

Obj.prototype.outerFunc = function() 
{
    var x = 0;
    var callback = this.innerFunc;
    x = callback(x);
}

Obj.prototype.innerFunc = function(x)
{
    x++;
    return x;
}

Note that the value is sent to the other function, not the variable. So you need to return the value and assign it in order to use it.

Sign up to request clarification or add additional context in comments.

2 Comments

Should've mentioned but I'm trying to avoid passing x in as an argument (see edit I made to original question)
@sookie This is precisely what functions are supposed to avoid.
0

If you're using prototypes, just set an instance property:

// constructor
var Obj = function () {}

Obj.prototype.outerFunc = function() 
{
   this.x = 0;
   var callback = this.innerFunc.bind(this);
   callback();
}

Obj.prototype.innerFunc = function()
{
   this.x++;
}

var instance = new Obj()
instance.outerFunc()
console.log(instance.x) // returns 1

Edit: But @lonesomeday's answer is a much better solution as it takes a more functional approach avoiding side effects :)

1 Comment

Sorry, should've mentioned but I'm actually trying to avoid making x an instance of Obj (see edit I made to original question)
0

This is a bit hard to solve without knowing why you don't want to pass a parameter; if you just want to have a specific function signature, maybe a higher-order function might help?

Obj.prototype.outerFunc = function() 
{
    var x = 0;
    var callback = this.innerFunc(x);
    callback();
}

Obj.prototype.innerFunc = function(x)
{
    return function () { /* use x in here */ };
}

This way you have two functions one inside the other. The outer one takes the parameter, and the inner one can access the variable that is passed to the outer one.

This of course only gives you half of what you demonstrate in your example: You can access the local variable but not modify it.

Comments

0

You can never access any function's internal variables from outside the function under any circumstances, in an OOP context or otherwise.

The only sort-of-exception is that a function A defined inside a function B, and returned from that function B, continues to have access to the variables in function B--the basic notion of closure.

I have no idea why you don't want to use instance variables. That's what they're for--sharing data across methods. I have no idea why you don't want to pass values in or out--that's what parameters and return values are for.

can I extend innerFunc's scope in order to access x?

No, you can't, whatever that means. There is no such notion in JS.

The closest you can come to what you seem to maybe want to do is to define the variable in the constructor:

function Obj() {
  var x = 0;

  this.outerFunc = function() {
    var callback = this.innerFunc;
    callback();
  };

  this.innerFunc = function() {
    x++;
  }
}

However, this will not work as-is because this.innerFunc is missing its context. Therefore, you would need to write

var callback = () => this.innerFunc();

However, it's a mystery why you would want to do this instead of just writing this.innerFunc().

Comments

0

The preferred way of doing this is to assign x to the scope of the object then all functions can access it, via this.x

Obj.prototype.outerFunc = function() 
{
    this.x= 0; // set x to zero
    this.innerFunc();
}

Obj.prototype.innerFunc = function(x)
{
    this.x++;
    return this.x;
}

2 Comments

Thanks. I'm actually trying to avoid making x an instance of Obj (see edit I made to original question)
If you can add the prototype within outerFunc then x would be accessible, or if you can make x a global outside of the object.

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.