在浏览器中使用这段Javascript:
<script>
console.log(window.someThing);
var x = 12;
function foo() {
window.otherThing = x;
}
</script>
在foo
内,我们可以访问window
,我们都知道,但为什么呢?
script
标记内)是否将它作为隐式局部变量,并且它只是“闭包继承”,就像任何其他局部变量一样(如上面的x
)可以吗?这是如何与script
标记内直接声明的变量一致,设置为window
的属性? (或者不是这样吗?)
<script>
var x = 12;
function() {
console.log(window.x);
}
</script>
答案 0 :(得分:23)
您可以在ECMAscript中访问“超出范围”或“免费”变量的原因是所谓的范围链。范围链是每个执行上下文的特殊属性。如前所述,上下文对象至少看起来像:
每次在上下文(例如函数)中访问变量(-name)时,查找过程总是从它自己的Activation Object
开始。所有形式参数,函数声明和本地定义的变量(var)都存储在该特殊对象中。如果在该对象中找不到变量名,搜索将进入[[Scope]]
- 链。每次初始化函数(-context)时,它都会将所有父上下文变量/激活对象复制到其内部[[Scope]]
属性中。这就是我们所说的词法范围。这就是 Closures 在ECMAscript中工作的原因。由于Global context
也有Variable Object
(更准确地说,**全局对象的变量对象是全局对象本身),它也会被复制到函数 [[Scope]] < / em> property。
这就是您可以从任何功能中访问window
的原因: - )
上面的解释有一个重要的概念结论:ECMAscript中的任何函数都是 Closure ,这是真的。由于每个函数都至少会复制 [[Scope]] 属性中的全局上下文VO 。
答案 1 :(得分:14)
Javascript中窗口真的是全局的吗?
是。除非您在更窄的范围内创建一个名为window的新变量
function foo() {
var window;
}
在foo里面,我们可以访问窗口,我们都知道,但为什么呢?
任何函数都可以访问在更广范围内声明的变量。那里的窗户没什么特别的。
答案 2 :(得分:7)
它全部在ECMAScript中定义。
全球是一个没有外部词汇环境的词汇环境。所有其他环境都嵌套在其中,并绑定到具有规范指定属性的全局对象。
这将全局对象的属性放在作用域链的起始处,所有其他环境都从该作用域继承。
ES 10.2.3 The Global Environment:
全局环境是一个独特的词法环境,它在执行任何ECMAScript代码之前创建。全局环境的Environment Record是一个对象环境记录,其绑定对象是全局对象(15.1)。全局环境的外部环境引用为null。
执行ECMAScript代码时,可能会向全局对象添加其他属性,并且可能会修改初始属性。
在控制进入任何执行上下文之前创建唯一的全局对象。
除非另有说明,否则全局对象的标准内置属性具有属性{[[Writable]]:true,[[Enumerable]]:false,[[Configurable]]:true}。
全局对象没有[[Construct]]内部属性;不可能将全局对象用作new运算符的构造函数。
全局对象没有[[Call]]内部属性;无法将全局对象作为函数调用。
全局对象的[[Prototype]]和[[Class]]内部属性的值取决于实现。
除了本规范中定义的属性外,全局对象还可能具有其他主机定义的属性。这可能包括一个属性,其值是全局对象本身;例如,在HTML文档对象模型中,全局对象的window属性是全局对象本身。
答案 3 :(得分:6)
它与范围链有关。
查看以下presentation of Nicholas C. Zakas。 (从5分钟左右开始)
答案 4 :(得分:3)
窗口是所有javascript对象的基本范围,它自动&#34;附加&#34;对于您定义的每个变量,除非您使用&#34; var&#34;在声明之前,在这种情况下变量的范围是本地的(这意味着它包含在父函数中,或者在其他情况下也是全局的,如果你在函数块之外声明你的变量) 。此外,窗口被定义为常量,即您无法重新定义窗口对象(您将收到错误说&#34;输入错误:重新声明const窗口&#34;)。
这样:
window.foo = 5;
它与:
相同var foo = 5;
或:
function() {
foo = 5;
}
但:
function() {
var foo = 5;
}
在这种情况下&#34; foo&#34;是本地的(window.foo === undefined)
答案 5 :(得分:1)
window
全局范围仅适用于主线程。在Web工作者中,没有window
个全局变量。相反,您有WorkerGlobalScope
inside a WebWorker
和SharedWorkerGlobalScope
inside a SharedWorker
。
此工作线全局范围存储在名为self
的变量中,并且MDN对其进行描述:
此范围包含Window个对象通常传达的信息。
当您在Web工作者中使用的第三方代码正在使用窗口对象时,这可能会成为问题。这可以通过his answer here中@FelipeMicaroniLalli建议的window
变量来轻松解决:
var window = self;
答案 6 :(得分:0)
在书Javascript: The Good Parts中,据我所知,Douglas Crockford解释说window
是包含所有全局变量的Web浏览器的全局对象。就像一环......