@[TOC]
ES6新特性(Symbol之后的)
Symbol 基本使用
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol特点
- Symbol的值是唯一的,用来解决命名冲突的问题
- Symbol值不能与其他数据进行运算
- Symbol 定义的对象属性不能使用 for...in 循环遍历,但是可以使用
Reflect.ownKeys来获取对象的所有键名
// 创建 Symbol
let s1 = Symbol ();
console .log( s1 , typeof s1 );
// 添加标识的 Symbol
let s2 = Symbol ( '尚硅谷' );
let s2_2 = Symbol ( '尚硅谷' );
console .log( s2 === s2_2 );
// 使用 Symbol for 定义
let s3 = Symbol .for( '尚硅谷' );
let s3_2 = Symbol .for( '尚硅谷' );
console .log( s3 === s3_2 );
Symbil的内置值
除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
| 恭喜 | 发财 |
|---|---|
| Symbol.hasInstance | 当其他对象使用 instanceof 运算符,判断是否为该对的实例时,会象调用这个方法 |
| Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。 |
| Symbol.species | 创建衍生对象时,会使用该属性 |
| Symbol.match | 当执行 str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。 |
| Symbol.replace | 当该对象被 str.replace(myObject)方法调用时,会返回该方法的返回值。 |
| Symbol.search | 当该对象被 str.search (myObject)方法调用时,会返回该方法的返回值。 |
| Symbol.split | 当该对象被 str.split(myObject)方法调用时,会返回该方法的返回值。 |
| Symbol.iterator | 对象进行 for...of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器 |
| Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。 |
| Symbol. toStringTag | 在该对象上面调用 toString 方法时,返回该方法的返回值 |
| Symbol. unscopables | 该对象指定了使用 with 关键字时,哪些属性会被 with环境排除。 |
迭代器
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
1. ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
2. 原生具备 iterator 接口的数据(可用 for of 遍历)
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
3. 工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
==注: 需要自定义遍历数据的时候,要想到迭代器。==
生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
function * gen(){
yield '一只没有耳朵';
yield '一只没有尾巴';
return '真奇怪';
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next())
代码说明:
* 的位置没有限制
生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
next 方法可以传递实参,作为 yield 语句的返回值
Promise
Promise 是 ES6 引入的异步编程的新==解决方案==。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
Promise 构造函数: Promise (excutor) {}
Promise.prototype.then 方法
Promise.prototype.catch 方法
Set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
size 返回集合的元素个数
add 增加一个新元素,返回当前集合
delete 删除元素,返回 boolean 值
has 检测集合中是否包含某个元素,返回 boolean 值
clear 清空集合,返回 undefined
//创建一个空集合
let s = new Set();
//创建一个非空集合
let s1 = new Set([1,2,3,1,2,3]);
//集合属性与方法
//返回集合的元素个数
console.log(s1.size);
//添加新元素
console.log(s1.add(4));
//删除元素
console.log(s1.delete(1));
//检测是否存在某个值
console.log(s1.has(2));
//清空集合
console.log(s1.clear());
Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:
size 返回 Map 的元素个数
set 增加一个新元素,返回当前 Map
get 返回键名对象的键值
has 检测 Map 中是否包含某个元素,返回 boolean 值
clear 清空集合,返回 undefined
//创建一个空 map
let m = new Map();
//创建一个非空 map
let m2 = new Map([
['name','尚硅谷'],
['slogon','不断提高行业标准']
]);
//属性和方法
//获取映射元素的个数
console.log(m2.size);
//添加映射值
console.log(m2.set('age', 6));
//获取映射值
console.log(m2.get('age'));
//检测是否有该映射
console.log(m2.has('age'));
//清除
console.log(m2.clear());
class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
class 声明类
constructor 定义构造函数初始化
extends 继承父类
super 调用腹肌构造方法
static 定义静态方法和属性
父类方法可以重写
//父类
class Phone {
//构造方法
constructor(brand, color, price) {
this.brand = brand;
this.color = color;
this.price = price;
}
//对象方法
call() {
console.log('我可以打电话!!!')
}
}
//子类
class SmartPhone extends Phone {
constructor(brand, color, price, screen, pixel) {
super(brand, color, price);
this.screen = screen;
this.pixel = pixel;
}
//子类方法
photo(){
console.log('我可以拍照!!');
}
playGame(){
console.log('我可以玩游戏!!');
}
//方法重写
call(){
console.log('我可以进行视频通话!!');
}
//静态方法
static run(){
console.log('我可以运行程序')
}
static connect(){
console.log('我可以建立连接')
}
}
//实例化对象
const Nokia = new Phone('诺基亚', '灰色', 230);
const iPhone6s = new SmartPhone('苹果', '白色', 6088,
'4.7inch','500w');
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法
SmartPhone.run();
数值扩展
二进制和八进制
ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。
Number.isFinite() 与 Number.isNaN()
Number.isFinite() 用来检查一个数值是否为有限的 Number.isNaN() 用来检查一个值是否为 NaN
Number.parseInt() 与 Number.parseFloat()
ES6 将全局方法 parseInt 和 parseFloat,移植到 Number 对象上面,使用不变。
Math.trunc
用于去除一个数的小数部分,返回整数部分。
Number.isInteger
Number.isInteger() 用来判断一个数值是否为整数
对象扩展
ES6 新增了一些 Object 对象的方法
Object.is 比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)
Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象
__proto__、setPrototypeOf、 setPrototypeOf 可以直接设置对象的原型
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的好处
模块化的优势有以下几点:
防止命名冲突
代码复用
高维护性
模块化规范产品
ES6 之前的模块化规范有:
CommonJS => NodeJS、Browserify
AMD => requireJS
CMD => seaJS
ES6 模块化语法
模块功能主要由两个命令构成:export 和 import。
- export 命令用于规定模块的对外接口
- import 命令用于输入其他模块提供的功能
ECMASript 7 新特性
Array.prototype.includes
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
指数操作符
在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
ECMASript 8 新特性
async 和 await
async 和 await 两种语法结合可以让异步代码像同步代码一样
async 函数
async 函数的返回值为 promise 对象
promise 对象的结果由 async 函数执行的返回值决定
await 表达式
await 必须写在 async 函数中
await 右侧的表达式一般为 promise 对象
await 返回的是 promise 成功的值
await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理
Object.values 和 Object.entries
Object.values()方法返回一个给定对象的所有可枚举属性值的数组
Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
Object.getOwnPropertyDescriptors
该方法返回指定对象所有自身属性的描述对象
ECMASript 9 新特性
Rest/Spread 属性
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符
function connect({host, port, ...user}) {
console.log(host);
console.log(port);
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
正则表达式命名捕获组
ES9 允许命名捕获组使用符号『?』,这样获取捕获结果可读性更强
let str = '<a href="http://www.atguigu.com">尚硅谷</a>';
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;
const result = reg.exec(str);
console.log(result.groups.url);
console.log(result.groups.text);
正则表达式反向断言
ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。
//声明字符串
let str = 'JS5211314 你知道么 555 啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);
正则表达式 dotAll 模式
正则表达式中点.匹配除回车外的任何单字符,标记『s』改变这种行为,允许行终止符出现
let str = `
<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul>`;
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){
data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);