JavaScript真的是全球性的吗?
在浏览器中使用这段JavaScript:
<script> console.log(window.someThing); var x = 12; function foo() { window.otherThing = x; } </script>
我们可以进入window
,我们都知道,但为什么呢?
- 这是一种特殊的全局variables吗?
- 还是“根范围”(在
script
标签内)有它作为一个隐式的局部variables,它是简单的“闭包inheritance”,因为任何其他局部variables(如上面的x
)可以是?
那么如何才能将script
标签中直接声明的variables设置为window
属性呢? (或者不是这样?)
<script> var x = 12; function() { console.log(window.x); } </script>
您可以在ECMAscript中访问“超出范围”或“自由”variables的原因就是所谓的范围链 。 作用域链是每个执行上下文中的一个特殊属性。 正如之前几次提到的,上下文对象看起来至less是这样的:
- [[范围]]
- variables/激活对象
- “这个”上下文值
每次你在一个上下文(例如一个函数)中访问一个variables(-name)时,查找过程总是从它自己的Activation Object
。 所有forms参数,函数声明和本地定义的variables(var)都存储在该特殊对象中。 如果在该对象中找不到variables名,search将进入[[Scope]]
链。 每次函数(-context)被初始化时,它都会将所有父上下文variables/激活对象复制到它的内部[[Scope]]
属性中。 这就是我们所说的词汇范围 。 这就是闭包在ECMAscript中工作的原因。 由于Global context
也有一个Variable Object
(更确切地说,**全局对象的variables对象是全局对象本身),它也被复制到函数[[Scope]]属性中。
这就是为什么你可以从任何function访问window
的原因:-)
上面的解释有一个重要的概念性结论:ECMAscript中的任何函数都是一个闭包 ,这是正确的。 由于每个函数至less会在其[[Scope]]属性中复制全局上下文VO 。
JavaScript真的是全球性的吗?
是。 除非在较窄的范围内创build一个名为window的新variables
function foo() { var window; }
我们可以进入窗口,我们都知道,但为什么呢?
任何函数都可以访问在更广泛范围内声明的variables。 那里的窗户没什么特别的。
它全部在ECMAScript中定义。
全球化是一个没有外在词汇环境的词汇环境。 所有其他环境都嵌套在其中,并且绑定到具有由spec指定的属性的全局对象。
这将全局对象的属性放在作用域链的开始处,所有其他环境都从其inheritance。
ES 10.2.3全球环境 :
全球环境是在任何ECMAScript代码执行之前创build的唯一的词法环境。 全局环境的环境logging是一个对象环境logging,其绑定对象是全局对象(15.1)。 全球环境的外部环境参考为空。
当ECMAScript代码被执行时,可以将其他属性添加到全局对象,并且可以修改初始属性。
ES 15.1全球对象
唯一的全局对象是在控制进入任何执行上下文之前创build的。
除非另外指定,否则全局对象的标准内置属性的属性为{[[Writable]]:true,[[Enumerable]]:false,[[Configurable]]:true}。
全局对象没有[[Construct]]内部属性; 新操作符不能用全局对象作为构造函数。
全局对象没有[[Call]]内部属性; 作为一个函数调用全局对象是不可能的。
全局对象的[[Prototype]]和[[Class]]内部属性的值是依赖于实现的。
除了本规范中定义的属性之外,全局对象还可以具有其他主机定义的属性。 这可能包括一个属性,其价值是全局对象本身; 例如,在HTML文档对象模型中,全局对象的窗口属性是全局对象本身。
它与范围链有关 。
看一下Nicholas C. Zakas的演讲 。 (从5分钟左右开始)
窗口是所有JavaScript对象的基本范围,它会自动“附加”到您定义的每个variables,除非在声明之前使用“var”,在这种情况下,variables的范围是本地的(也就是说它包含在父函数,否则也是全局的,如果你正在声明你的variablesfunction块外)。 而且窗口被定义为一个常量 ,那就是你不能重新定义窗口对象 (你会得到一个错误,说“types错误:重新声明const窗口”)。
所以:
window.foo = 5;
这是一样的:
var foo = 5;
要么:
function() { foo = 5; }
但:
function() { var foo = 5; }
在这种情况下,“foo”是本地的(window.foo === undefined)
在我的理解书中, Javascript:The Good Parts ,道格拉斯·克罗克福德(Douglas Crockford)解释说, window
是包含所有全局variables的Web浏览器的全局对象。 这就像一个戒指…
window
全局范围仅适用于主线程。 在networking工作者没有window
全局variables。 相反,您可以在WebWorker
和SharedWorkerGlobalScope
内的SharedWorker
。
这个web worker全局作用域存储在一个名为self
的variables中,正如MDN所描述的那样:
这个范围包含通常由Window对象传递的信息。
当您在web worker中使用的第三方代码正在使用窗口对象时,这可能会成为问题。 这可以很容易地通过@FelipeMicaroniLalli在他的回答中声明一个window
variables来解决,就像这样:
var window = self;