为什么全局作用域中的变量会被赋值给 window 对象?

3
var foo = 'bar';
console.log(window.foo); // bar

看起来变量被赋值为this的属性,但在匿名函数内部,this指的是父级作用域,但不会将变量赋值给父级作用域。

function() {
    var foo = 'bar';
}();

window.foo; // undefined

在非全局作用域中,变量被分配给哪个对象?
4个回答

5

引用http://perfectionkills.com/understanding-delete/#execution_context

每个执行上下文都有一个所谓的Variable Object与之关联。类似于执行上下文,变量对象是一个抽象实体,一种描述变量实例化的机制。现在,有趣的部分是,在源文本中声明的变量和函数实际上被添加为此变量对象的属性。

当控制进入全局代码的执行上下文时,使用Global object作为Variable object。这正是为什么全局声明的变量或函数成为Global object属性的原因。

然而,这些Variable Object是不可访问的。唯一的非内部变量是全局对象windowthis(在全局上下文中)。

规范中相关的部分是#10: Executable Code and Execution Contexts


那么window对象存在的唯一目的就是作为全局的变量对象吗? - Cameron Martin
1
Ecmascript本身不需要window对象。*全局对象可能具有其他主机定义的属性。*例如,HTML规范定义了Window接口 - Bergi

2
在JavaScript中,所有变量都被分配给某个作用域对象。然而,只有全局变量的作用域对象可以通过浏览器中的window对象访问。函数作用域中的变量被分配给JavaScript运行时内部使用的某些作用域对象,但用户无法访问该对象。
在其他环境中,全局变量可能作为另一个对象的属性可访问(例如在Node.js中的GLOBAL),或者可能不可访问(例如在Windows脚本宿主程序中运行的应用程序脚本)。

为什么全局作用域对象不是内部的,或者反过来,为什么非全局作用域对象不能被访问?看起来不一致。 - Cameron Martin
任何作用域对象都不能直接访问。但是,任何代码片段都可以访问其自身作用域中的变量以及父级作用域中的变量。恰好全局作用域是所有其他作用域对象的父级作用域,这就是为什么它始终可用的原因。 - Gareth
@Gareth提出了一个很好的观点。如果我们可以直接访问所有作用域对象,垃圾回收器将会在清理引用时遇到困难。全局作用域包含了所有其他作用域,因此它始终可用,并且只能在脚本终止时进行垃圾回收。 - Mattias Buelens

0

它们仅在声明它们的函数中可用。

JavaScript 中只有函数作用域,不像其他语言(如使用 {} 的块作用域)。

关于您的编辑 不要被愚弄了 - 在我看来,JS 的 this 语义有点让人恼火 - 在各种情况下,this 可能不是您预期的内容。


是的,我的编辑有误。关于你的帖子:为什么全局变量要分配给窗口对象呢? - Cameron Martin
@ddlshack 因为在浏览器上下文中,那就是全局作用域所在的位置。 - Dave Newton

0

在自调用匿名函数内,例如:

function() {
    ....
}()

所有变量都保留在其中,不会附加到全局对象或window。使用这种技术,可以创建模式,例如module/singleton pattern

请注意,在JS中,变量具有函数级别作用域。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接