Aaron Yodaiken
Aaron Yodaiken

Reputation: 19551

specifics of closures in JavaScript and anonymous functions

This code results in "!" being logged on the console.

var g = {};
(function() {
    var t = this;
    t.x = "x";
    g.a = function() {
        console.log(t.x);
    };
})();

(function() {
    var t = this;
    t.x = "!";
    g.b = function() {
        console.log(t.x);
    };
})();

g.a();

Do anonymous functions share a this? Am I using this wrong? I don't really understand what's going on here.

I'd like for g.a() to continue returning the value of x defined in the first anonymous function.

I'm using node.js if it makes a difference.

Upvotes: 5

Views: 452

Answers (3)

jfriend00
jfriend00

Reputation: 707298

When I look at this script in the debugger in Chrome as you've shown it, the "this" value in both anonymous functions is set to the global variable "window". That means that each anonymous function is setting the value of window.x so the last one executed wins and is the value that survives, thus window.x == "!" after the second anonymous function executes.

It's unclear to me what you expected "this" to be or what you're actually trying to accomplish with this code so I don't know what alternative to suggest. If you just want the previous state in the anonymous function to survive for the internal function, then you can just rely on local variables (which will survive in the closure) and not use the "this" reference at all. Squeegy's example shows that.

Upvotes: 1

Felix Kling
Felix Kling

Reputation: 816384

In the immediate functions, this refers to the global object [docs]. So in this case in both functions this indeed refers to the same element and you are overwriting x with the second call.

What object this refers to is determined by how the function is called.

  • If you just execute a function with funcName();, then this refers to the global object.
  • If the function is assigned to a property of an object, obj.funcName() , this refers to the object.
  • If you call the function with the new operator, new funcName();, this refers to an empty object that inherits from the functions prototype.

You can also explicitly set this by using call [docs] or apply [docs].


Instead referring to this, you could create a new object in both functions:

var t = {};

Additional note: It makes no difference whether you run the code in the browser or with node.js. The global object is part of the specification and has to be provided by the execution environment. In browsers it is the window object, I don't what it is in node.js, but it does not matter as long as it follows the specification.

Upvotes: 4

Alex Wayne
Alex Wayne

Reputation: 187024

Felix Kling is the right long answer. But I wanted to chime in with what I think you actually want:

var g = {};
(function() {
    var x = "x";
    g.a = function() {
        console.log(x);
    };
})();

(function() {
    var x = "!";
    g.b = function() {
        console.log(x);
    };
})();

g.a(); // "x"
g.b(); // "!"

Now g.a() and g.b() both print out x, but each function has their own separate x shared with the closure. If these vars should be private an only accessible internally to each of these functions, this is how you hide them and persist them through multiple calls.

Upvotes: 3

Related Questions