最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

scope - JavaScript local scoping: var vs. this - Stack Overflow

programmeradmin5浏览0评论

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?

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?
Share Improve this question asked Feb 23, 2013 at 23:23 AlphaAlpha 7,8688 gold badges60 silver badges95 bronze badges 8
  • 5 Why would they work alike? Seems like you're analogizing with Java or some other language where the this namespace is implicit, which is not the case for JS. – Fabrício Matté Commented Feb 23, 2013 at 23:28
  • @FabrícioMatté I may be unconscious doing this (pun intended). I fail to understand if the scoping should make variables/members automatically exposed to inner members. It seems that it is not the case, because it's not consistent. – Alpha Commented Feb 23, 2013 at 23:33
  • 3 @Alpha You're paring variables (var a = 5;) with things that are not variables but properties of objects (this.b = 10; sets the property b of the object that this refers to to 10). These things are not the same and therefore do not behave identically. – Niko Commented Feb 23, 2013 at 23:35
  • I'm thinking about a simple way to explain it, but basically JS's lexical scope won't automatically expose members to inner members as you've said. – Fabrício Matté Commented Feb 23, 2013 at 23:36
  • 1 @Alpha see how 4 changes if you did innerMethod.call(this); or this.method = innerMethod; and (new MyObject()).method(); – Paul S. Commented Feb 23, 2013 at 23:38
 |  Show 3 more ments

3 Answers 3

Reset to default 4

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/wiki/Scope_(puter_science)

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

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

发布评论

评论列表(0)

  1. 暂无评论