JavaScript本地范围:var与此相对

时间:2013-02-23 23:23:22

标签: javascript scope scoping

我似乎无法理解JavaScript变量的特定范围。与我发现的其他示例和问题不同,我对嵌套函数的范围感兴趣。

我在this JSFiddle设置了一个示例。相关部分如下:

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
    }
}

现在,我了解对a的引用直接有效。 我也理解消息3和4(this.athis.b)将失败,因为this指的是内部函数。我也理解第6行是有效的,因为我保存了对原始对象的引用。

我不明白的是:

  • 为什么消息1和2不一样?
  • 为什么第5和第6条消息不一样?

3 个答案:

答案 0 :(得分:4)

a变量就是变量。它在innerMethod(它只是一个嵌套函数)的范围内可见,如a,它是如何声明的(即JavaScript具有词法作用域规则,内部函数可以看到函数的变量)它们是在里面定义的。

thisMyObject构造函数的本地范围不同。

您已经看到selfthis MyObject的别名,而innerMethod已在其自己的范围内覆盖this。尽管如此,由于this不是函数范围的别名,因此self.athis.a都不会在这里工作。

有关词汇范围的更严格的解释,您可以例如从维基百科开始:http://en.wikipedia.org/wiki/Scope_(computer_science)

您可以在ECMA标准http://es5.github.com/#x10.3

中了解执行上下文和标识符解析规则

答案 1 :(得分:1)

这是范围的问题,当创建函数时,它们会保存周围环境(包括变量)。

因此,在创建innerMethod时,它可以看到变量selfa

一个重要的概念是,在声明函数时创建范围,而不是在调用函数时创建范围。

在您的情况1中,b未被声明(此对象不相同)。

在案例5和案例6中,您没有创建self.a

答案 2 :(得分:0)

主要原因是self innerMethod 范围内不等于thisthis是引用该函数所有者的关键字。对于 innerMethod ,它不是实例方法,它属于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();

您可以在here

进行游戏