JavaScript本地作用域:var与this
我似乎无法理解JavaScript变量作用域的具体情况。与我发现的其他示例和问题不同,我对嵌套函数的范围感兴趣 我在学校树立了一个榜样。有关部分如下:JavaScript本地作用域:var与this,javascript,scope,scoping,Javascript,Scope,Scoping,我似乎无法理解JavaScript变量作用域的具体情况。与我发现的其他示例和问题不同,我对嵌套函数的范围感兴趣 我在学校树立了一个榜样。有关部分如下: function MyObject() { var self = this; var a = 1; this.b = 2; var innerMethod = function() { //1 and 2: direct reference logMessage("a = " +
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.a
和this.b
)将失败,因为this
指的是内部功能。我也知道第6行是有效的,因为我保存了对原始对象的引用
我不明白的是:
- 为什么消息1和消息2不一样
- 为什么消息5和消息6不一样
- 这是作用域的问题,创建函数时,它们会保存周围环境(包括变量)
因此,当创建
innerMethod
时,它可以看到变量self
和a
一个重要的概念是,范围是在声明函数时创建的,而不是在调用函数时创建的
在您的案例1中,b
未被声明(此对象的名称不同)
在案例5和案例6中,您没有创建
self。一个变量就是一个变量。它在innerMethod
(这只是一个嵌套函数)的范围内可见,正如a
,这就是它的声明方式(即JavaScript具有词法范围规则,内部函数可以看到它们在其中定义的函数的变量)
此
与MyObject
构造函数的本地范围不同
您已经看到,self
是MyObject
的this
的别名,并且innerMethod
在其自身范围内覆盖了this
。但是,由于this
不是函数作用域的别名,因此self.a
和this.a
都不会在这里工作
要更严格地解释词汇范围,您可以从维基百科开始:
您可以阅读ECMA标准中的执行上下文和标识符解析规则主要原因是self
在innerMethod范围内不等于this
<代码>此
是引用函数所有者的关键字。对于innerMethod,它不是实例方法,它属于窗口
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();
你可以在上玩,为什么它们都一样?似乎您在用Java或其他语言进行类比,其中这个
名称空间是隐式的,而JS则不是这样。@FabriciomattéI可能无意识地这样做(双关语)。我不明白作用域是否应该使变量/成员自动暴露给内部成员。似乎不是这样,因为它不一致。@Alpha您正在将变量(var a=5;
)与不是变量而是对象属性的事物(this.b=10;
设置this
引用的对象的属性b
)。这些东西不一样,因此行为也不相同。我想用一种简单的方法来解释它,但基本上JS的词法作用域不会像你说的那样自动将成员暴露给内部成员。@Alpha如果你调用了innerMethod.call(这个),请看4的变化
或this.method=innerMethod
和(新的MyObject()).method()
我更喜欢第三段中的术语,而不是函数范围
,并声明第一段背后的原因是JS有。但是解释得很好。我已经合并了您的一些更改,但是我对用VariableEnvironment交换函数范围犹豫不决。尽管它在技术上更为正确,但我相信函数作用域这个概念对于来自其他语言的程序员来说更为广为人知。我已将您的链接添加到ECMA标准。