是“窗口” JavaScript 真的是全局的吗?

发布于 2024-11-19 20:39:17 字数 696 浏览 4 评论 0原文

在浏览器中获取这段 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>

Take this piece of JavaScript code in a browser:

<script>
    console.log(window.someThing);
    var x = 12;

    function foo() {
       window.otherThing = x;
    }
</script>

Inside foo we can access window. We all know that, but why exactly?

  • Is it some kind of special global variable?
  • Or does the "root scope" (inside the script tag) have it as an implicit local variable and is it simply "closure-inherited" as any other local variable (like x above) can be?

And how does that concur with variables declared directly inside the script tag being set as properties of window? (Or is that not so?)

<script>
    var x = 12;
    function() {
       console.log(window.x);
    }
</script>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

隔岸观火 2024-11-26 20:39:17

之所以可以在 ECMAScript 中访问“超出范围”“自由”变量,就是所谓的作用域链。作用域链是每个执行上下文的特殊属性。正如之前多次提到的,上下文对象至少看起来像:

  • [[scope]]
  • 变量/激活对象
  • “this”上下文值

每次在上下文(例如函数)中访问变量(名称)时,查找进程始终在其自己的激活对象中启动。所有形式参数、函数声明和本地定义的变量 (var) 都存储在该特殊对象中。如果在该对象中未找到变量名,则搜索将进入[[Scope]]链。

每次初始化函数(-context)时,它都会将所有父上下文变量/激活对象复制到其内部[[Scope]]属性中。这就是我们所说的词法范围。这就是为什么闭包在 ECMAScript 中工作的原因。由于全局上下文也有一个变量对象(更准确地说,**全局对象的变量对象是全局对象本身),它也会被复制到函数< em>[[范围]] 属性。

这就是为什么你可以从任何函数中访问窗口 :-)

上述解释有一个重要的概念性结论:ECMAScript 中的任何函数都是一个闭包,这是正确的。因为每个函数至少会复制其[[Scope]]属性中的全局上下文VO

The reason why you can access "out of scope" or "free" variables in ECMAScript is the so-called scope chain. The scope chain is a special property from each execution context. As mentioned several times before, a context object looks at least like:

  • [[scope]]
  • Variable / Activation Object
  • "this" context value

Each time you access a variable(-name) within a context (a function for instance), the lookup process always starts in its own Activation Object. All formal parameters, function declarations and locally defined variables (var) are stored in that special object. If the variablename was not found in that object, the search goes into the [[Scope]]-chain.

Each time a function(-context) is initialized, it'll copy all parent context variable/activation objects into its internal [[Scope]] property. That is what we call, a lexical scope. That is the reason why closures work in ECMAScript. Since the Global context also has an Variable Object (more precisely, **the variable object for the global object is the global object itself) it also gets copied into the functions [[Scope]] property.

That is the reason why you can access window from within any function :-)

The above explanation has one important conceptional conclusion: Any function in ECMAScript is a closure, which is true. Since every function will at least copy the global context VO in its [[Scope]] property.

故人如初 2024-11-26 20:39:17

JavaScript 中的 window 真的是全局的吗?

是的。除非你在更窄的范围内创建一个名为 window 的新变量

function foo() {
    var window;
}

在 foo 内部我们可以访问 window,我们都知道这一点,但到底为什么呢?

任何函数都可以访问在更广泛的范围内声明的变量。那里的窗户没有什么特别的。

Is window really global in JavaScript?

Yes. Unless you create a new variable called window in a narrower scope

function foo() {
    var window;
}

Inside foo we can access window, we all know that, but why exactly?

Any function can access variables declared in a wider scope. There is nothing special about window there.

情绪操控生活 2024-11-26 20:39:17

这一切都是在 ECMAScript 中定义的。

全局是一个词法环境,没有外部词法环境。所有其他环境都嵌套在其中,并绑定到具有规范指定的属性的全局对象。

这会将全局对象的属性放置在作用域链的开头,所有其他环境都从该作用域链中继承。

ES 10.2.3 全球环境

全局环境是一个独特的词法环境,它是在执行任何 ECMAScript 代码之前创建的。全局环境的环境记录是一个对象环境记录,其绑定对象是全局对象(15.1)。全局环境的外部环境引用为空。

执行 ECMAScript 代码时,可能会向全局对象添加其他属性,并且可能会修改初始属性。

ES 15.1 全局对象

唯一的全局对象是在控制进入任何执行上下文之前创建的。

除非另有说明,全局对象的标准内置属性具有属性 {[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}。

全局对象没有[[Construct]]内部属性;无法将全局对象用作带有 new 运算符的构造函数。

全局对象没有[[Call]]内部属性;无法将全局对象作为函数调用。

全局对象的 [[Prototype]] 和 [[Class]] 内部属性的值取决于实现。

除了本规范中定义的属性之外,全局对象还可能具有其他主机定义的属性。这可能包括一个值为全局对象本身的属性;例如,在 HTML 文档对象模型中,全局对象的 window 属性就是全局对象本身。

It's all defined in ECMAScript.

The global is a lexical environment that doesn't have an outer lexical environment. All other environments are nested within it, and is bound to a global object with properties specified by the specification.

This places the properties of the global object at the start of the scope chain, from which all other environments inherit.

ES 10.2.3 The Global Environment:

The global environment is a unique Lexical Environment which is created before any ECMAScript code is executed. The global environment’s Environment Record is an object environment record whose binding object is the global object (15.1). The global environment’s outer environment reference is null.

As ECMAScript code is executed, additional properties may be added to the global object and the initial properties may be modified.

ES 15.1 The Global Object

The unique global object is created before control enters any execution context.

Unless otherwise specified, the standard built-in properties of the global object have attributes {[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}.

The global object does not have a [[Construct]] internal property; it is not possible to use the global object as a constructor with the new operator.

The global object does not have a [[Call]] internal property; it is not possible to invoke the global object as a function.

The values of the [[Prototype]] and [[Class]] internal properties of the global object are implementation-dependent.

In addition to the properties defined in this specification the global object may have additional host defined properties. This may include a property whose value is the global object itself; for example, in the HTML document object model the window property of the global object is the global object itself.

嘦怹 2024-11-26 20:39:17

它与作用域链有关。

观看Nicholas C. Zakas 的演示(从5 分钟)。

It has to do with the scope chain.

Have a look at the presentation of Nicholas C. Zakas (starting around 5 minutes).

疯狂的代价 2024-11-26 20:39:17

window 是所有 JavaScript 对象的基本作用域,它会自动“附加”到您定义的每个变量,除非您在声明之前使用“var”,在这种情况下,变量的作用域是本地的(这意味着它包含在父函数内,或者如果您在函数块之外声明变量,那么它也是全局的)。而且window被定义为常量*,即你不能重新定义window object(您将收到一条错误消息“类型错误:重新声明 const 窗口”)。

所以:

window.foo = 5;

它与:

var foo = 5;

或者:

function() {
    foo = 5;
}

但是:

function() {
    var foo = 5;
}

在这种情况下,“foo”是本地的(window.foo === undefined),

window is the base scope of all JavaScript objects, and it's automatically "attached" to each variables you define, unless you use "var" before the declaration, in this case the scope of the variable it's local (that means that it's contained inside the parent function, or is otherwise global too, if you are declaring your variable outside a function block). Moreover window is defined as a constant*, that is you can't redefine the window object (you will get an error saying "type error: redeclaration of const window").

So:

window.foo = 5;

It's the same as:

var foo = 5;

Or:

function() {
    foo = 5;
}

but:

function() {
    var foo = 5;
}

In this case, "foo" is local (window.foo === undefined),

海未深 2024-11-26 20:39:17

window 全局范围仅适用于主线程。在 Web Worker 中,没有 window 全局变量。相反,您在 中有 WorkerGlobalScope WebWorkerSharedWorkerGlobalScope 位于 SharedWorker 内。

这个工作全局范围存储在一个名为 self 的变量中,正如 MDN 所描述的:

此范围包含通常由 Window 传达的信息对象。

当您在 Web Worker 中使用的第 3 方代码使用 window 对象时,这可能会成为问题。这可以通过声明一个 window 变量来轻松解决,正如 @FelipeMicaroniLalli 在他的答案中所建议的那样像这样:

var window = self;

The window global scope applies only to the main thread. In web workers there is no window global variable. Instead you have WorkerGlobalScope inside a WebWorker and in a SharedWorkerGlobalScope inside a SharedWorker.

This worker global scope is stored in a variable called self and as MDN describes it:

this scope contains the information usually conveyed by Window objects.

This can become a problem when 3rd party code you are using in your web worker is using the window object. This can be easily solved by declaring a window variable as suggested by @FelipeMicaroniLalli in his answer here like this:

var window = self;
素衣风尘叹 2024-11-26 20:39:17

据我了解,在 JavaScript: The Good Parts 一书中,Douglas Crockford 解释了 window< /code> 是包含所有全局变量的 Web 浏览器的全局对象。就像一环一样...

In the book JavaScript: The Good Parts, as I understand, Douglas Crockford explains that window is the global object of the web browser that contains all the global variables. It is like the One Ring...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文