1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 10:22:23 +00:00

docs(let): edit let/global

This commit is contained in:
ruanyf 2016-10-08 01:35:33 +08:00
parent d95493c10a
commit ddf6220289
2 changed files with 68 additions and 6 deletions

View File

@ -533,9 +533,9 @@ var constantize = (obj) => {
ES5只有两种声明变量的方法`var`命令和`function`命令。ES6除了添加`let``const`命令,后面章节还会提到,另外两种声明变量的方法:`import`命令和`class`命令。所以ES6一共有6种声明变量的方法。 ES5只有两种声明变量的方法`var`命令和`function`命令。ES6除了添加`let``const`命令,后面章节还会提到,另外两种声明变量的方法:`import`命令和`class`命令。所以ES6一共有6种声明变量的方法。
## 全局对象的属性 ## 顶层对象的属性
全局对象是最顶层对象,在浏览器环境指的是`window`对象在Node.js指的是`global`对象。ES5之中全局对象的属性与全局变量是等价的。 顶层对象,在浏览器环境指的是`window`对象在Node指的是`global`对象。ES5之中顶层对象的属性与全局变量是等价的。
```javascript ```javascript
window.a = 1; window.a = 1;
@ -545,11 +545,11 @@ a = 2;
window.a // 2 window.a // 2
``` ```
上面代码中,全局对象的属性赋值与全局变量的赋值,是同一件事。对于Node来说这一条只对REPL环境适用模块环境之中全局变量必须显式声明成`global`对象的属性。) 上面代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。
未声明的全局变量,自动成为全局对象`window`的属性,这被认为是JavaScript语言最大的设计败笔之一。这样的设计带来了两个很大的问题首先是没法在编译时就报出变量未声明的错误只有运行时才能知道其次程序员很容易不知不觉地就创建了全局变量比如打字出错。另一方面从语义上讲,语言的顶层对象是一个有实体含义的对象,也是不合适的。 顶层对象的属性与全局变量挂钩,被认为是JavaScript语言最大的设计败笔之一。这样的设计带来了两个很大的问题首先是没法在编译时就报出变量未声明的错误只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的而属性的创造是动态的);其次程序员很容易不知不觉地就创建了全局变量(比如打字出错)。另一方面,`window`对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。
ES6为了改变这一点一方面规定为了保持兼容性`var`命令和`function`命令声明的全局变量,依旧是全局对象的属性;另一方面规定,`let`命令、`const`命令、`class`命令声明的全局变量,不属于全局对象的属性。也就是说从ES6开始全局变量将逐步与全局对象的属性脱钩。 ES6为了改变这一点一方面规定为了保持兼容性`var`命令和`function`命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,`let`命令、`const`命令、`class`命令声明的全局变量,不属于顶层对象的属性。也就是说从ES6开始全局变量将逐步与顶层对象的属性脱钩。
```javascript ```javascript
var a = 1; var a = 1;
@ -561,4 +561,65 @@ let b = 1;
window.b // undefined window.b // undefined
``` ```
上面代码中,全局变量`a``var`命令声明,所以它是全局对象的属性;全局变量`b``let`命令声明,所以它不是全局对象的属性,返回`undefined` 上面代码中,全局变量`a``var`命令声明,所以它是顶层对象的属性;全局变量`b``let`命令声明,所以它不是顶层对象的属性,返回`undefined`
## 顶层对象
ES5的顶层对象本身也是一个问题因为它在各种实现里面是不统一的。
- 浏览器里面,顶层对象是`window`但Node和Web Worker没有`window`
- 浏览器和Web Worker里面`self`也指向顶层对象但是Node没有`self`
- Node里面顶层对象是`global`,但其他环境都不支持。
为了能够在各种环境,都能取到顶层对象,现在一般是使用`this`变量。
- 全局环境中,`this`会返回顶层对象。但是Node模块和ES6模块中`this`返回的是当前模块。
- 函数里面的`this`,如果函数不是作为对象的方法运行,而是单纯作为函数运行,`this`会指向顶层对象。但是,严格模式下,这时`this`会返回`undefined`
- 不管是严格模式,还是普通模式,`new Function('return this')()`总是会返回全局对象。但是如果浏览器用了CSPContent Security Policy内容安全政策那么`eval``new Function`这些方法都可能无法使用。
综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。下面是两种勉强可以使用的方法。
```javascript
// 方法一
(typeof window !== 'undefined'
? window
: (typeof process === 'object' &&
typeof require === 'function' &&
typeof global === 'object')
? global
: this);
// 方法二
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
```
现在有一个[提案](https://github.com/tc39/proposal-global),在语言标准的层面,引入`global`作为顶层对象。也就是说,在所有环境下,`global`都是存在的,都可以从它拿到顶层对象。
垫片库[`system.global`](https://github.com/ljharb/System.global)模拟了这个提案,可以在所有环境拿到`global`
```javascript
// CommonJS的写法
require('system.global/shim')();
// ES6模块的写法
import shim from 'system.global/shim'; shim();
```
上面代码可以保证`global`对象存在。
```javascript
// CommonJS的写法
var global = require('system.global')();
// ES6模块的写法
import getGlobal from 'system.global';
const global = getGlobal();
```
上面代码将顶层对象放入一个变量。

View File

@ -40,6 +40,7 @@
- Axel Rauschmayer, [Variables and scoping in ECMAScript 6](http://www.2ality.com/2015/02/es6-scoping.html): 讨论块级作用域与let和const的行为 - Axel Rauschmayer, [Variables and scoping in ECMAScript 6](http://www.2ality.com/2015/02/es6-scoping.html): 讨论块级作用域与let和const的行为
- Nicolas Bevacqua, [ES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth](http://ponyfoo.com/articles/es6-let-const-and-temporal-dead-zone-in-depth) - Nicolas Bevacqua, [ES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth](http://ponyfoo.com/articles/es6-let-const-and-temporal-dead-zone-in-depth)
- acorn, [Function statements in strict mode](https://github.com/ternjs/acorn/issues/118): 块级作用域对严格模式的函数声明的影响 - acorn, [Function statements in strict mode](https://github.com/ternjs/acorn/issues/118): 块级作用域对严格模式的函数声明的影响
- Axel Rauschmayer, [ES proposal: global](http://www.2ality.com/2016/09/global.html): 顶层对象`global`
## 解构赋值 ## 解构赋值