ciso
ciso

Reputation: 3050

Access to variables in scope from a function defined externally

Is there a way to print the value of temp (a closure variable) from a function defined outside the closure but referenced within the closure without passing temp as a variable to funcA?

var funcA, funcB;

funcA = function () {
   console.log(temp);
}

funcB = function () {var temp, funcC;
  temp = 1;
  funcC = funcA;
  funcC();
}
funcB();  // temp is undefined.

This works, but only because funcA is defined within funcB:

funcB = function () {var temp, funcA, funcC;
  temp = 1;
  funcA = function () {
       console.log(temp);
  }
  funcC = funcA;
  funcC();
}
funcB(); // 1

I'm trying to find a way to pull some function definitions out of outer functions to streamline code that's getting a little complex. Can I define funcA outside of funcB but still reference the temp variable without having to pass parameters?

I read that javascript does not have dynamic run time scoping, that it's only lexical scoping, but with referencing a function (funcA via funcC) within funcB, is there a way to meet the lexical scope requirement and provide access to the scoped variables for funcB?

Upvotes: 1

Views: 109

Answers (2)

Reactgular
Reactgular

Reputation: 54771

Yes, and No.

The keyword var for declaring variables behaves different depending upon what the current scope is. When var is executed on the global scope it is optional. The variable becomes a property of the global object. When executing in the browser this global object is window.

So the following in global space has the same result.

var temp = 1;
window.temp = 1;
this.temp = 1;

All the above is just window.temp because of the global context.

When you use var inside a function then the variable is attached to the function. All functions in Javascript are objects so local var variables will live as long as the parent function is still being used somewhere.

Javascript will walk the hierarchy of executing scopes to find a variable identifier. So any inner functions can access their outer function variables (as in your example).

What you can do is play around with the this reference in functions.

The identifier this in Javascript is dynamic (meaning that you can change it). I can pass a variable to an unknown function that was declared outside the calling function. Since the this.temp is used to reference the variable the function funcA is able to display the value.

funcB = function(otherFunc)
{
    this.temp = 1;
    otherFunc();
}

funcA = function()
{
    alert(this.temp);
}

funcB(funcA);

http://jsfiddle.net/thinkingmedia/dfLvj/

See the above jsfiddle example.

What you can do with this is change the meaning of this on the fly. Here is a better example.

funcB = function(otherFunc)
{
    var temp = {
        message: "Hello World!"
    };
    var foo = otherFunc.bind(temp);
    foo();
}

funcA = function()
{
    alert(this.message);
}

funcB(funcA);

http://jsfiddle.net/thinkingmedia/K5Pw6/

Dynamically changing this can have a lot of benefits by allowing a function to accept closure references that will be executed with a custom this reference.

An example might be a click event handler where this is the DOM element that triggered the event.

Upvotes: 1

ciso
ciso

Reputation: 3050

Using Akinkunle Allen's comment, I came up with this which seems to solve my problem.

function funcB () {
  var funcA, funcB, temp;

  funcA = function () {
     console.log(temp);
  }

  funcB = function () {var funcC;
    temp = 1;
    funcC = funcA;
    funcC(); 
  }
  return funcB();
}

funcB(); // 1

Upvotes: 1

Related Questions