1 let
1.1 基本语法
1.用法类似于var,但声明变量只在所在代码块中有效。
2.非常适用于for循环
注:(1)for循环设置部分为负作用域,循环体为单独子作用域。
(2)var 声明 变量 i,变量提升,全局有效, 循环指向的是同一i,a[i]相同
(3)let 声明 变量i,变量不提升,作用于有效,循环指向新变量i,a[i]不同
1.2不存在变量提升
- var存在变量提升
- let不存在变量提升
...
// let 的情况
console.log(bar); // 报错 ReferenceError
let bar = 2;
...
1.3暂时性死区(temporal dead zone,简称 TDZ)
1.块级作用域存在 let, 它所声明的变量 binding 这个区域,不受外部影响
在let命令声明变量tmp之前,都属于变量tmp的“死区”。
2.死区导致 typeof 可能出现错误
1.4 不允许重复声明
let不允许在相同作用域内,重复声明同一个变量
2. 块级作用域
2.1块级作用域的重要性
ES5只有 全局作用域 和 函数作用域,存在问题
- 内层变量可能覆盖外层变量
2.用来计数的循环变量泄露成全局变量
2.2 ES6的块级作用域
- let为js新增块级作用域
- es6允许块级作用域的任意嵌套
- 内层作用域可以定义外层作用域的同名变量
2.3 块级作用域与函数声明
1.es5不允许函数在块级作用域声明,只能在顶层作用域和函数作用于之中声明
2.es6允许函数在块级作用域声明,行为类似于let,不可在快回作用域外引用。
注:在es6浏览器中:
(1) 允许在块级作用域内声明函数
(2) 函数声明类似于var,会提升到全局作用域或者函数作用于的头部
(3) 函数声明还会提升至所在的块级作用域的头部
(4) 避免在块级作用域内声明函数
(5) 如需实现(4),请写成函数表达式
(6) es6作用域必须要有大括号
3 const命令
2.1 基础用法
- const声明一个只读常量,声明后,值不变
- const只在声明所在的块级作用域内有效
- const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用
- const不可重复声明
2.2 本质
const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动
2.3 声明变量的六种方法
var function let const import class
4顶层对象的属性
- 浏览器顶层对象是 window 对象
- node 顶层对象是 global 对象
- ES5 顶层对象 与 全局变量是等价的
存在问题:
(1)编译时无法报出变量未声明的错误
(2)程序员很容易不知不觉地就创建了全局变量
(3)顶层对象的属性是到处可以读写的
(4)window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含 义的对象,也是不合适的。
4 解决:
ES6 规定,
(1)为保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;
(2)let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
5 globalThis对象
5.1 顶层对象不统一
(1)浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
(2)浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
(3)Node 里面,顶层对象是global,但其他环境都不支持
5.2 用this取到顶层对象
(1)全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
(2)函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
(3)不管是严格模式,还是普通模式,new Function('return this')(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
5.3 取到顶层对象的方法
// 方法一
(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');
};
5.4 globalThis提案
引入globalThis作为顶层对象