简体   繁体   中英

Access local variable of function inside callback

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
}

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.

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 :)

The preffered 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;
}

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.

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() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM