sabithpocker
sabithpocker

Reputation: 15566

What is the difference between scope of these two functions

I am sorry if this is too naive, just got stuck with this while trying to answer another question. :) Here in the code below both bar.x and bar.y has similar/same function body (does it matter where the function is initially declared?). And I guess that the scope of a foo is lost when it is assigned to y, but still when I call bar.y() why is it not taking the global_var inside its closure? Is there a way both x and y can output 300?

global_var = 2
var foo = function(){
  console.log("y", global_var)
}
var bar = (function b(){
  var global_var = 300;
  var x = function(){
    console.log("x",global_var);
  };
  var y = foo;
  return {x: x, y: y};
})();

bar.x(); //300
bar.y(); //2
setTimeout(bar.x); //300
setTimeout(bar.y); //2

Upvotes: 0

Views: 60

Answers (2)

JLRishe
JLRishe

Reputation: 101680

There is no closure involved in assigning foo to y. The function foo's scope is determined where is is defined, which is at the top of your code sample, and the global_var inside the body of that function will always refer to the global_var variable that is (implicitly) defined in line 1, and not any other variable with the same name.

Assigning foo to y has no effect on the scope of that function. All that assignment accomplishes is that it makes foo accessible from a new variable.

Is there a way both x and y can output 300?

Not when the function is defined like that, but you could have something similar to what you're expecting if you use this:

global_var = 2

var foo = function(){
  console.log("y", this.global_var)
}

var bar = (function b(){
  var global_var = 300;

  var x = function(){
    console.log("x", this.global_var);
  };

  var y = foo;

  return {x: x, y: y, global_var: global_var};
})();

foo();                       // 2

bar.x();                     // 300
bar.y();                     // 300

setTimeout(bar.x);           // 2
setTimeout(bar.y);           // 2

setTimeout(bar.x.bind(bar)); // 300
setTimeout(bar.y.bind(bar)); // 300

Upvotes: 1

Quentin
Quentin

Reputation: 943564

does it matter where the function is initially declared

Yes. The scope of a function is determined solely by where it is declared.

And I guess that the scope of a foo is lost when it is assigned to y

No. The scope is unchanged.

when I call bar.y() why is it not taking the global_var inside its closure?

Because the scope of a function is determined solely by where it is declared.

Is there a way both x and y can output 300?

Not by twiddling with scope.

You'd have to rewrite the function to get the data from somewhere else, e.g. from object properties.

var global_object = {};
global_object.data = 1;

global_object.foo = function() {
  console.log("y", this.data);
};

var bar = (function b() {
  var local_object = {};
  local_object.data = 2;
  local_object.x = function() {
    console.log("x", this.data);
  };
  local_object.y = global_object.foo;
  return local_object;
})();

bar.x(); // 2
bar.y(); // 2
setTimeout(bar.x.bind(bar)); // 2
setTimeout(bar.y.bind(bar)); // 2

Upvotes: 1

Related Questions