一、let和const命令
1. let命令
基本用法
ES6新增了let命令,用来声明变量。用法类似于var,但是也存在新特性:
1 | 1)let所声明的变量,只在let命令所在的代码块有效。适用于for循环。 |
块级作用域
let实际上为JavaScript新增了块级作用域。外层作用域无法读取内层作用域的变量,内层作用域可以定义外层作用域的同名变量。
1 | let foo = 1; |
块级作用域的出现,实际上使得广泛应用的立即执行函数表达式(IIFE)不再必要了。
2. const命令
基本用法
const声明一个只读的变量。一旦声明,常量的值就不能改变。
1 | 1)const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。 |
用途:为了防止意外修改变量,比如,引入库名,组件名等
let、const与var的区别:
1 | a. let、const有块级作用域的概念,只要是定义的变量,就是一个块级作用域;var只有在函数中才有作用域; |
作用域的概念:ES5有两个作用域:全局和局部
ES6有了块作用域的概念:块作用域,通俗的理解,就是一个大括号,就是一个块作用域;
ES6 声明变量的六种方法
ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。
顶层对象的属性
顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。ES5 之中,顶层对象的属性与全局变量是等价的。
1 | window.a = 1; |
上面代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。
顶层对象的属性与全局变量挂钩,是JavaScript 语言最大的设计败笔之一。ES6 为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
1 | var a = 1; |
上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。
globalThis 对象
JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。
1 | 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。 |
同一段代码为了能够在各种环境,都能取到顶层对象,现在一般是使用this变量,但是有局限性。
- 全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
- 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。
- 不管是严格模式,还是普通模式,new Function(‘return this’)(),总是会返回全局对象。但是,如果浏览器用了 CSP(Content Security Policy,内容安全策略),那么eval、new Function这些方法都可能无法使用。
综上所述,很难找到一种方法,可以在所有情况下,都取到顶层对象。下面是两种勉强可以使用的方法。
1 | // 方法一 |
现在有一个提案,在语言标准的层面,引入globalThis作为顶层对象。也就是说,任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指向全局环境下的this。
二、解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructing)。
1 | 以前,为变量赋值,只能直接指定值。 |
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。如果结构不成功,变量的值就等于undefined。另一种情况是不完全解构,即等号左边的模式只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
数组的解构赋值
1 | let [a,b,c] = [1,2,3]; |
对象的解构赋值
1 | 1)对象的属性没有次序,变量必须与属性同名,才能取到正确的值 |
对象的解构也可以指定默认值。
1 | var {x = 3} = {}; |
字符串的解构赋值
1 | 1)解构时,字符串被转换成了一个类似数组的对象。 |
数值和布尔值的解构赋值
1 | 解构时,如果等号右边是数值和布尔值,则会先转为对象。 |
函数参数的解构赋值
1 | 1)基本语法 |
常见用途
1 | 1)交换变量的值 |
三、字符串、正则、对象、函数、数组等扩展
字符串的扩展
字符串的遍历器接口
1 | for (let codePoint of 'foo') { |