JavaScript ES6
ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准。
一、ES6
1. 什么是 ES6 ?
ES6 是 JavaScript 的下一代标准。
2. 支持情况
ECMAScript 6 compatibility table
3. Babel
一般通过 Babel 进行转码,它可以将 ES6 代码转换为更具兼容性的语法,使其能够在旧版本的浏览器下运行。
二、let 和 const
1. let
let 用于声明一个仅在代码块内有效的变量。
作用域仅在块中:
使用 var 声明的变量没有块作用域
1
2
3
4
{
var x = 10;
}
// 此处可以访问到x使用 let 声明的变量仅能在代码块中访问
1
2
3
4
{
let x = 10;
}
// 此处无法访问到x变量覆盖问题:
var 可以重复声明,而 let 不行
1
2
3
4
5
6
7
// var可以重复声明
var a = 1;
var a = 2;
// let不能重复声明
let b = 3;
let b = 4;若代码块外部原有变量,在代码块中用 var 定义同名变量,将会覆盖代码块外的变量
1
2
3
4
5
6
7
var x = 10;
// 此处 x 为 10
{
var x = 6;
// 此处 x 为 6
}
// 此处 x 为 6使用 let 就可以解决这一问题
1
2
3
4
5
6
7
var x = 10;
// 此处 x 为 10
{
let x = 6;
// 此处 x 为 6
}
// 此处 x 为 10变量提升问题:
对于 var 来说,变量的声明将会被提升到作用域的顶端
1
2
3
4
5
6
// 在声明前使用,将不会报错
// 但由于未定义,因此将会输出undefined
console.log(a)
// 在使用后才声明并定义
var a = 5;对于 let 来说,不存在变量提升,因此在声明前使用将会报错
1
2
3
4
5
// 报错
console.log(a)
// 在使用后才声明并定义
let a = 5;迭代变量复用问题:
对于 var 来说,迭代变量会重用,从而可能导致执行结果不符合预期
1
2
3
for (var i = 0; i < 5; i++ ) {
setTimeout(() => console.log(i), 0); // 5 5 5 5 5
}对于 let 来说,每次迭代循环都会声明一个新的迭代变量
1
2
3
for (let i = 0; i < 5; i++ ) {
setTimeout(() => console.log(i), 0); // 0 1 2 3 4
}
2. const
const 用于声明常变量。
- 声明后不允许改变
- 因为声明后不允许改变,因此应该在声明时初始化
- const 保证变量值不变,因此,如果变量为引用类型,变量所指向的内存地址不允许改变,但内存地址上的值可以改变
三、解构赋值
1. 说明
对象的解构赋值针对 对象/数组 进行模式匹配,对其中的变量进行赋值。
2. 数组的解构赋值
希望从数组中提取值,对变量进行赋值。
不使用解构赋值语法:
1 |
|
使用结构赋值语法:
1 |
|
3. 对象的解构赋值
对象的结构赋值与数组的不同在于:
数组元素是按次序排列的,变量只需要按顺序排列即可取到值;
而对象的属性没有次序,变量必须和属性同名才能取到正确的值。
不使用解构赋值语法:
1 |
|
使用结构赋值语法:
1 |
|
使用解构赋值语法,且变量名不对应:
1 |
|
4. 默认值
解构赋值允许指定默认值,当且仅当对应 数组元素/对象成员 严格等于 undefined 时,默认值才会生效。
1 |
|
5. 应用
(1) 获取对象的方法
通过对象的解构赋值,可以获取对象的方法并赋给变量。
获取 console.log:
1
const { log } = console
获取对数、正弦、余弦方法:
1
const { log, sin, cos } = Math
(2) 交换变量值
1 |
|
四、Symbol
1. 说明
Symbol 是 ES6 引入的新数据类型,用于表示独一无二的值。
2. 基本使用
1 |
|
3. 注意点
Symbol 变量的类型为 symbol
1
2let a = Symbol("描述")
// typeof(a)的值为symbol若将 Symbol 变量 log,将会展示描述
1
2let a = Symbol("描述")
console.log(a) // Symbol("描述")每个 Symbol 的值都是唯一的,即使他们的描述相同
1
2
3let a = Symbol("描述")
let b = Symbol("描述")
console.log(a === b) // falseSymbol 作为属性名时,无法被
for in/of
、Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
访问如果希望获取对象的 Symbol 属性,可以通过
Object.getOwnPropertySymbols()
和Reflect.ownKeys()
4. Symbol.for()
首先全局搜索被登记的 Symbol 中是否有以指定字符串作为描述的 Symbol,如果有则返回,如果没有则新建并登记。
1 |
|
5. Symbol.keyFor()
该方法可以接收一个已被登记的 Symbol,返回其描述。
1 |
|
4. 应用 - 作为属性名
因为 Symbol 的值都是不相等的,因此可以作为对象的属性名,从而保证对象的属性不重名。
1 |
|
需要注意的是:
Symbol 作为对象属性名时,不能使用
.
运算符,而应该使用[]
。因为
.
运算符之后总是字符串,因此会读取到 Symbol 的 toString 值,而不会读取到 Symbol 的值。
五、Map 和 Set
1. Map
(1) 说明
Map 用于保存键值对。
(2) 特点
- Map 的 key 可以为任何值
- Map 的键值对是有序的
- Map 的键值对个数可以通过 size 属性获取
2. Set
Set 对象用于存储一堆值,这些值应该是唯一的。
六、Reflect 和 Proxy
待更
七、字符串
1. 字符串的识别
在 ES6 之前,如果希望判断字符串中是否包含字串,需要借助
indexOf()
方法。
ES6 新增了以下实例方法:
includes()
:判断字符串中是否包含子串,返回布尔值startsWith()
:判断字符串是否以子串开头,返回布尔值endsWith()
:判断字符串是否以字串结尾,返回布尔值
2. 字符串重复
repeat()
方法用于将字符串重复指定次数后返回。
1
2
let str = "hello".repeat(2)
// str的值为 "hellohello"
- 如果参数是小数,则向下取整
- 如果参数在
-1 ~ 0
之间,则取整至 0- 如果参数为负数,报错
- 如果参数为 Infinity,报错
- 如果参数为 NaN,取整至 0
- 如果参数为字符串,会尝试将字符串转换为数字
3. 字符串补全
padStart()
:接受一个字符串参数,将其从头部补全原字符串,返回新字符串padEnd()
:接受一个字符串参数,将其从尾部补全原字符串,返回新字符串
4. 模板字符串
(1) 多行字符串
可以通过 `` ` 符号来定义多行字符串。
1
2
3
let str = `Hello,
World`
console.log(str);
(2) 插入变量、表达式、函数
可以在被 `` 符号包裹的字符串中,使用
${}` 插入变量、表达式、函数。
1
2
3
4
5
6
7
8
9
10
let name = "小张"
let birthYear = 2000
let sayHi = function(name) {
return "你好呀!" + name
}
let str =
`姓名:${name}
年龄:${2021 - birthYear}
欢迎词:${sayHi(name)}`
console.log(str)
(3) 作为函数参数
模板字符串可以作为函数参数,并且可以简化函数的调用
当模板字符串为纯字符串时,
1
fun`hello`
等价于:
1
fun("hello")
当模板字符串带有变量、表达式、函数时,JavaScript 会将模板字符串处理为多个参数,具体处理方法为:
- 将模板字符串挨个拆分
- 拆分后的字符串部分组成字符串数组,作为函数的第 1 个参数
- 拆分后的变量、表达式、函数部分依次排开,作为函数的第 2、… 、n 个参数
1
f`My Name is ${name},I am ${age+1} years old next year.`;
等价于:
1
f(['My Name is',',I am ',' years old next year.'],'Mike',28);
八、数值
待更
九、对象
1. 属性的简洁表示
ES6 允许用变量简洁表示对象的属性,无需显式给出对象属性的属性名和属性值,而是直接填入变量即可,此时变量名将作为属性名,而变量值将作为属性值。
非简洁表示:
1
2
3
4
let user1 = {
name: "小张",
age: 20
}简洁表示:
1
2
3
4
5
6
let name = "小张"
let age = 20
let user1 = {
name,
age
}
2. 方法的简洁表示
对于对象中的方法,允许进行简写。
非简洁表示:
1
2
3
4
5
let user1 = {
sayHi: function(){
console.log("Hi");
}
}简洁表示:
1
2
3
4
5
let user1 = {
sayHi(){
console.log("Hi");
}
}
3. 表达式做属性/方法名
ES6 允许使用表达式作为属性/方法名,只需要将表达式用 []
包裹即可。
1
2
3
4
let user = {
["na" + "me"]: "小张",
[isWorker ? "wid" : "uid"]: "1001"
}
4. 扩展运算符
(1) 作用
扩展运算符 ...
的作用是:取出目标对象中的所有可遍历属性,拷贝至当前对象之中。
(2) 基本用法
1 |
|
此段代码将对象 1 **中的可遍历属性拷贝至对象 2 **之中,从而实现了对象的 “不完全深拷贝”。
假设对象的成员为对象/数组,拷贝时将拷贝”指针”,而非完整拷贝。
(3) 合并对象
1 |
|
5. Object.assign()
1 |
|
Object.assign()
方法用于将对象中的可遍历属性拷贝至目标对象之中,从而实现对象的 “不完全拷贝”。
6. Object.is()
1 |
|
用于判断两个对象是否严格相等,与 ===
类似。
十、数组
待更
十一、函数
1. 参数默认值
可以为函数的参数指定默认值。
1 |
|
当且仅当未传递参数或参数为 undefined 时,参数的默认值才会生效
2. 不确定个数的参数
ES6 允许不确定个数的参数,该参数只能有一个,并且只能放在参数的最后。
所有不确定个数的 “多余参数” 将会组成一个数组,传递给函数。
1 |
|
3. 箭头函数
(1) 简化书写
箭头函数允许用较为简短的语句编写函数表达式。
1 |
|
箭头函数的进一步简化:
1 |
|
(2) this 问题
对于箭头函数而言,函数中的 this 指的是定义函数时的 this,而非使用函数时的 this 。
十二、Class 类
1. 说明
在 ES6 中引入了 Class 类这一概念,它可以看作一个语法糖,本质上是对象构造函数。
2. 基本语法
(1) 类的定义
使用 class
定义类;
类中可以书写成员属性和成员方法;
使用 constructor
定义构造函数,在其中初始化对象。
1 |
|
(2) 类的实例化
1 |
|
3. 类的继承
通过 extends
实现继承,通过 super
调用父类方法。
1
2
3
4
5
6
7
8
class Cat extends Animal {
constructor(···) {
···
super(···);
}
}
4. 寄存器
可以通过 get 和 set 定义对原有属性的封装,控制对原有属性的访问及修改。
1 |
|
需要注意的是:
- 属性名与访问器名不能相同,否则会陷入死循环
- get 和 set 必须成对出现
十三、模块化
具体请看:
十四、Promise
具体请看:
十五、Generator
待更
十六、async
1. async function
1 |
|
async 关键字放置于 function 之前,它将会创建一个异步函数,函数将异步执行并返回 Promise 对象。
2. await
1 |
|
await 操作符后跟 Promise 对象
也可以后跟其它表达式,表达式将会立刻执行并返回结果
await 操作符只能在异步函数中使用
await 表达式
将会等待 Promise 执行结束,并返回执行结果