原文链接:http://javascript.info/global-object,translate with ❤️ by zhangbao.

当 JavaScript 创建的时候,一个“全局对象”的概念,它提供了全局变量和函数。浏览器里的多个脚本共享同一个全局对象。

从那时起,JavaScript 就发生了很大的变化,通过全局变量连接代码的想法变得不那么有吸引力了。在现代JavaScript中,模块的概念取代了它的位置。

但是全局对象仍然留存在规范里。

在浏览器中,它叫“window”,在 Node.js 中,它叫“global”,其他环境里的全局对象的名字也可能不一样。

全局对象做两件事:

  1. 提供访问内置函数和值的通道,在规范和环境对象中定义的。例如,我们可以直接调用 alert,或者作为 window 的方法调用:
  1. alert("Hello");
  2. // 等同于
  3. window.alert("Hello");

这种状况也适应于其他内置对象。比如,我们可以使用 window.Array 而不是 Array。

  1. 提供了访问全局函数声明和 var 变量。这些东西我们可以作为全局对象的属性读写。例如:
  1. var phrase = "Hello";
  2. function sayHi() {
  3. alert(phrase);
  4. }
  5. // 从 window 中读取
  6. alert( window.phrase ); // Hello (全局 var)
  7. alert( window.sayHi ); // function (全局函数声明)
  8. // 可以像 window 写入(创建一个新的全局变量)
  9. window.test = 5;
  10. alert(test); // 5

但是通过 let/const 方式声明的变量是无法在全局对象上获得的。

  1. let user = "John";
  2. alert(user); // John
  3. alert(window.user); // undefined, let 声明的变量不存在于全局对象中
  4. alert("user" in window); // false

注:全局对象不是全局环境记录

在 ES-2015 之前的 ECMAScript 规范中,没有 let/const 声明,只有 only。全局对象被用作全局环境记录(文字有点不同,但这就是要点)。

但从 ES-2015 年开始,这些实体就分开了,全局词法环境有了它的环境记录。有一个全局对象提供了一些全局变量。

作为一个实际的区别,全局 let/const 变量是全局环境记录的绝对属性,但是它们在全局对象中并不存在。

自然,这是因为将全局对象作为一种访问“所有全局事事物”的方式来自远古时代。现在不被认为是一件好事。现代语言的特性,比如 let/const 不和它交朋友,但是对旧的语言仍然是兼容的。

“window”的使用

在像 Node.js 这样的服务器端环境中,globval 这个全局对象很少使用,嗯……也许说“从不”才对。

但在浏览器里,window 有时就被用到。

通常,使用它不是一个好主意,但是这里有一些你可能遇到的例子。

  1. 如果在一个函数里取到与本地变量同名的全局变量。
  1. var user = "Global";
  2. function sayHi() {
  3. var user = "Local";
  4. alert(window.user); // 全局
  5. }
  6. sayHi();

这样的使用是一种变通方法。最好以不同的方式命名变量,这样就不需要用这种方式编写代码了,请注意在 user 之前的“var”。这个技巧不适用于 let 变量。

  1. 检查某个全局变量或内置函数是否存在。

例如,我们想检查全局函数 XMLHttpRequest 是否存在

我们不能写成 if (XMLHttpRequest),因为如果这里没有 XMLHttpRequest,就会报错的(变量未定义)。

但是我们可以读取 window.XMLHttpRequest:

  1. if (window.XMLHttpRequest) {
  2. alert('XMLHttpRequest exists!')
  3. }

如果没有这样的全局函数 window.XMLHttpRequest 只算作是一个不存在对象属性。其值是 undefined,不会报错,是有效的。

我们也可以用另一种不用 window 的方式:

  1. if (typeof XMLHttpRequest == 'function') {
  2. /* is there a function XMLHttpRequest? */
  3. }

它不使用窗口,但是(理论上)不太可靠,因为 typeof 可能使用的是本地 XMLHttpRequest,而我们想要的是全局的 XMLHttpRequest。

  1. 从正确的窗口取这个变量,这可能是最有效的用例。

浏览器可以打开多个窗口和选项卡。一个窗口也可以在