Frage

I can't seem to get my head around a specific case of scoping for JavaScript variables. Different from other examples and questions I have found, I am interested in the scoping for nested functions.

I've set up an example at this JSFiddle. The relevant part is the following:

function MyObject() {
    var self = this;

    var a = 1;
    this.b = 2;

    var innerMethod = function() {
        //1 and 2: direct reference
        logMessage("a = " + a); // a = 1
        //logMessage("b = " + b); // Error: b is not defined

        //3 and 4: using this
        logMessage("this.a = " + this.a); // this.a = undefined
        logMessage("this.b = " + this.b); // this.b = undefined

        //5 and 6: using self
        logMessage("self.a = " + self.a); // self.a = undefined
        logMessage("self.b = " + self.b); // self.b = 2
    }
}

Now, I understand that a reference to a directly works. I also understand that messages 3 and 4 (this.a and this.b) will fail because this refers to the internal function. I also understand that line 6 works because I save the reference to the original object.

What I do not understand is:

  • why aren't messages 1 and 2 working alike?
  • why aren't messages 5 and 6 working alike?
War es hilfreich?

Lösung

The a variable is just that, a variable. It's visible in the scope of innerMethod (which is just a nested function), as a, which is how it was declared (ie. JavaScript has lexical scoping rules, inner functions can see variables of the functions they're defined inside of).

this isn't the same as the local scope of the MyObject constructor.

You've seen that self is an alias for this of MyObject, and that innerMethod has overwritten this in its own scope. Still, since this is not an alias for function scope, neither self.a nor this.a will ever work here.

For a more rigorous explanation of lexical scoping you can e.g. start at wikipedia: http://en.wikipedia.org/wiki/Scope_(computer_science)

You can read about the execution contexts and identifier resolution rules in the ECMA standard http://es5.github.com/#x10.3

Andere Tipps

It's a problem with scope, when functions are created they save their surroundings (including variables).

So when innerMethod is created, it can see variables self and a.

An important concept is that the scope is created when the function is declared, instead of when it is called.

In your case 1, b is not being declared (the this object is not the same).

In cases 5 and 6, you did not create self.a.

The main reason is that self is not equal to this in scope of innerMethod. this is a keyword to reference the owner of the function. For innerMethod, it is NOT a instance method, it belongs to the Window.

function MyObject() {
    var self = this;

    var innerMethod = function() {
        alert("inner method, self == this?: " + self == this); // false
        alert("inner method: " + this); // [object Window]
        alert("closest constructor name of in prototype chain ?: "+ this.__proto__.constructor.name); // Window
    }

    this.outerMethod = function(){
        innerMethod(); 
        alert("outer method: " + this); // [object MyObject]
        alert("closest constructor name in prototype chain?: "+ this.__proto__.constructor.name); // MyObject
    }
}

var o = new MyObject();
o.outerMethod();

You can play at here

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top