目录

前言:用此篇文章来记录一下常用的ES6-10的新增知识。

1. ECMASript 6(2015)

1.1 let 关键字

let关键字用来声明变量,使用let声明的变量有以下特点:

  • 不允许重复声明
  • 块级作用域
  • 不允许变量提升
  • 不影响作用域链

1.2 const关键字

const关键字用来声明变量,const声明有以下特点:

  • 声明变量必须赋初始值
  • 标识符一般大小
  • 不允许重复声明
  • 值不允许修改
  • 块级作用域

注意:对象属性修改和数组元素修改不会发生const错误

使用场景:声明对象类型使用const,声明非对象属性使用let

1.3 变量的解构赋值

ES6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。

//数组的解构赋值
const arr = ['张学友', '刘德华', '黎明', '郭富城'];
let [zhang, liu, li, guo] = arr;
//对象的解构赋值
const lin = {
name: '林志颖',
tags: ['车手', '歌手', '小旋风', '演员']
};
let {name, tags} = lin;

使用场景:频繁使用对象方法、数组元素,就可以使用解构赋值。

1.4 模板字符串

模板字符串是增强版的字符串,使用反引号(`)进行表示,特点如下:

  • 字符串中可以出现换行符
  • 可以使用​​${ XXX}​​形式输出变量

使用场景:当遇到字符串与变量拼接的情况使用模板字符串

1.5 简化对象的写法

ES6允许大括号里面,直接写入变量和函数,作为对象的属性和方法。

let name = "hello"
let fn = function(){}

let obj = {
name,
fn
}

使用场景:对象简写的形式简化了代码,所以能简写的最好简写

1.6 箭头函数

ES6允许使用箭头来定义函数。使用箭头函数需要注意以下几点:

  • 如果参数只有一个,则小括号可以省略
  • 如果函数体只有一条语句,则大括号可以省略,函数的返回值就是该语句的执行结果
  • 箭头函数本身没有this,它的this执行它所在的作用域下的this值
  • 箭头函数不能作为构造函数进行实例化
  • 不能使用arguments

使用场景:箭头函数不能改变this的指向,适合用来指定回调函数

1.7 rest参数

ES6引入了rest参数,用于获取函数的实参,用来代替arguments

需要注意,rest参数必须是最后一个形参。

rest参数可以用以下用途:

  • 当参数个数不确定时
function rest(...arr) {
for (let item of arr) {
console.log(item);
}
}
rest(1, 3, 5);
  • 当参数个数不确定时,已知某些参数
function rest02(item, ...arr) {
console.log(item); // 1
console.log(arr); // [2, 3]
}
rest02(1, 2, 3);
  • 进行解构赋值
var [a,...temp]=[1, 2, 3];
console.log(a); // 1
console.log(temp); // [2,3]

1.8 spread 扩展运算符

扩展运算符:​​...​​ 它就像是rest参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。

spread 扩展运算符可以有以下用途:

  • 将数组转化为用逗号分隔的参数序列
function  test(a,b,c){
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
}

var arr = [1, 2, 3];
test(...arr);
  • 将一个数组拼接到另一个数组
var arr1 = [1, 2, 3,4];
var arr2 = [...arr1, 4, 5, 6];
console.log(arr2); // [1, 2, 3, 4, 4, 5, 6]
  • 将字符串转为逗号分隔的数组
var str='JavaScript';
var arr= [...str];
console.log(arr); // ["J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]

1.9 Symbol

ES6中引入了一个新的基本数据类型Symbol,表示独一无二的值。它是一种类似于字符串的数据类型,它的特点如下:

  • Symbol的值是唯一的,用来解决命名冲突的问题
  • Symbol值不能与其他类型数据进行运算
  • Symbol定义的对象属性不能使用​​for...in​​​遍历循环,但是可以使用​​Reflect.ownKeys​​ 来获取对象的所有键名
let s1 = Symbol();
console.log(typeof s1); // "symbol"

let s2 = Symbol('hello');
let s3 = Symbol('hello');
console.log(s2 === s3); // false

使用场景:遇到唯一性的场景时可能会使用到Symbol

除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法,会在特定的情况下使用:

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环境排除

1.10 迭代器

迭代器(Iterator)实际上就是一种机制。它就是一个接口,为不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作。

(1) ES6 创造了一种新的遍历命令 ​​for...of​​​ 循环,Iterator 接口主要供 ​​for...of​​ 消费

(2)迭代器原理

  • 创建一个指针对象,指向当前数据结构的起始位置
  • 第一次调用对象的​​next​​方法,指针自动指向数据结构的第一个成员
  • 接下来不点调用​​next​​方法,指针一直往后移动,直到指向最后一个成员
  • 每次调用next方法返回一个包含​​value​​​和​​done​​属性的对象
//通过 Symbol.iterator 创建一个迭代器
const items = ["zero", "one", "two"];
const it = items[Symbol.iterator]();

it.next(); // {value: "zero", done: false}
it.next(); // {value: "one", done: false}
it.next(); // {value: "two", done: false}
it.next(); // {value: undefined, done: true}

(3)原生具备 iterator 接口的数据(可用 for of 遍历)

  • Array、TypedArray
for (let item of ["zero", "one", "two"]) {
console.log(item); // zero one two
}
  • Arguments
function args() {
for (let item of arguments) {
console.log(item); // zero one
}
}
args("zero", "one");
  • Set

Set 是对其元素进行迭代,迭代的顺序与其添加的顺序相同

const set = new Set();
set.add("zero");
set.add("one");

for (let item of set) {
console.log(item); // zero one
}
  • Map

Map 主要是迭代它们的 entries ,每个 entry 都会被编码为 [key, value] 的项, entries 是以确定的形式进行迭代,其顺序是与添加的顺序相同

const map = new Map();
map.set(0, "zero");
map.set(1, "one");

for (let item of map) {
console.log(item); // [0, "zero"] [1, "one"]
}
  • String

字符串是可迭代的,但他们遍历的是 Unicode 码,每个码可能包含一个到两个的 Javascript 字符。

for (const c of 'z\uD83D\uDC0A') {
console.log(c);
}

【JavaScript】ECMASript 6—10新增常用知识汇总_运算符

1.11 生成器

生成器函数是ES6提供的一种异步编程的解决方法,语法与传统函数完全不一样:

function * gen(){
yield 'hello';
yield 'world';
return 'JavaScript';
}
let iterator = gen();
console.log(iterator)
console.log(iterator.next()); // {value: "hello", done: false}
console.log(iterator.next()); // {value: "world", done: false}
console.log(iterator.next()); // {value: "JavaScript", done: true}

【JavaScript】ECMASript 6—10新增常用知识汇总_javascript_02


需要注意:

  • 生成器函数返回的结果是迭代器对象,调用迭代器对象的​​next​​​方法可以得到​​yield​​后面的值
  • ​yield​​​相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次​​next​​方法,执行一段代码
  • ​next​​​方法可以传递实参,这个参数会作为上一条执行的​​yield​​语句的返回值

1.12 Promise

Promise是ES6引入的异步编程的新的解决方案,在语法上,Promise是一个构造函数,用来封装异步操作可以获取其成功或失败的结果

  • Promise的构造函数:​​Promise(excutor){}​
  • ​Promise.prototype.then​​ 方法
  • ​Promise.prototype.catch​​ 方法

相关知识:《异步编程:Promise基础》

1.13 Set

ES6提供了新的数据结构Set(集合)。它类似于数组,但是成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符for…of… 进行遍历。

Set的属性和方法:

属性和方法

简介

size

返回集合的元素个数

add

增加一个新的元素,返回当前的集合

delete

删除元素,返回布尔值

has

检查集合中是否包含某元素,返回布尔值

clear

清空集合,返回undefined

//创建一个空集合
let s = new Set();
//创建一个非空集合
let s1 = new Set([1,2,3,1,2,3]);
//返回集合的元素个数
console.log(s1.size); // 3
//添加新元素
console.log(s1.add(4)); // {1,2,3,4}
//删除元素
console.log(s1.delete(1)); //true
//检测是否存在某个值
console.log(s1.has(2)); // true
//清空集合
console.log(s1.clear()); //undefined

1.14 Map

ES6提供了Map数据结构,它类似于对象,也是键值队的集合,但是它的key值不限于字符串,可以是任何类型的值,Map也实现了iterator接口,所以可以使用扩展运算符for…of… 进行遍历。

Map的属性和方法:

属性和方法

简介

size

返回Map的元素个数

set

增加一个新的元素,返回当前的Map

get

返回键名对象的键值

has

检查Map中是否包含某元素,返回布尔值

clear

清空Map,返回undefined

//创建一个空 map
let m = new Map();
//创建一个非空 map
let m2 = new Map([
['name', 'hello'],
]);
//获取映射元素的个数
console.log(m2.size); // 1
//添加映射值
console.log(m2.set('age', 6)); // {"name" => "hello", "age" => 6}
//获取映射值
console.log(m2.get('age')); // 6
//检测是否有该映射
console.log(m2.has('age')); // true
//清除
console.log(m2.clear()); // undefined

1.15 class类

ES6引入了类的概念,来作为对象的模板。通过class关键字可以定义类。ES6的class可以看做是一个语法糖,他的多数功能在ES5中也可以实现,新的class写法只是让对象原型的写法更加清晰,更像面向对象的编程语法。

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) {
super(brand, color, price);
this.screen = screen;
}
//子类方法
photo(){
console.log('可以拍照!');
}

//方法重写
call(){
console.log('视频通话!');
}
//静态方法
static run(){
console.log('运行程序')
}
}
//实例化对象
const Nokia = new Phone('诺基亚', '灰色', 230);
const iPhone = new SmartPhone('苹果', '白色', 6088, '5inch');
//调用子类方法
iPhone.photo();
//调用重写方法
iPhone.call();
//调用静态方法
SmartPhone.run();

1.16 数值扩展

ES6提供了二进制和八进制数值的新的写法,分别使用前缀​​0b​​​和​​0o​​表示。

还提供了一个关于数值的方法:

方法

简介

Number.isFinite()

用来检查一个数值是否为有限的

Number.isNaN()

用来检查一个值是否为 NaN

Number.parseInt()

将全局方法 ​​parseInt​​移植到 Number 对象上面,转换为整数

Number.parseFloat()

将全局方法 ​​parseFloat​​移植到 Number 对象上面,转换为浮点数

Math.trunc

用于去除一个数的小数部分,返回整数部分

Number.isInteger()

用来判断一个数值是否为整数

1.17 对象扩展

ES6新增了一些Object对象的方法:

  • Object.is():用来比较两个值是否严格相等,与===的行为基本一致,用法:​​Object.is(value1, value2)​
  • Object.assign():对象的合并,将源对象的所有可枚举属性,复制到目标对象,返回目标对象,用法:​​Object.assign(target, ...sources)​
  • ​__proto__​​​、​​setPrototypeOf​​ 可以直接设置对象的原型

1.18 模块化

使用模块化可以防止命名冲突、提高代码复用率、便于后期的维护。

ES6中的模块功能主要由两个命令构成:export 和 import

  • export 命令:用于规定模块的对外接口
  • import 命令:用于输入其他模块提供的功能

1.19 函数参数默认值

ES6支持在定义函数的时候为其设置默认值:

function foo(a = 1, b = 'hello')
{
// ...
}

2. ECMASript 7(2016)

2.1 Array.prototype.includes

Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值

语法如下:

  • arr.includes(searchElement)
  • arr.includes(searchElement, fromIndex)

参数其中:

  • ​arr​​是被检测的数组
  • ​searchElement​​是被检测的某个数据
  • ​fromIndex​​​是从某个索引值开始检测,如果为负值,则按升序从​​arr.length + fromIndex​​ 的索引开始搜索。默认为 0。可以省略

2.2 指数操作符

在 ES7 中引入指数运算符「​​**​​」,用来实现幂运算,功能与 Math.pow 结果相同

2**3 == Math.pow(2,3);

3. ECMASript 8(2017)

3.1 async和await

​async​​​和​​await​​可以让异步代码执行时和同步代码一样

(1)async

  • ​async​​​的返回值为​​promise​​对象
  • ​promise​​​对象的结果由​​async​​函数执行的返回值决定

(2)await

  • ​await​​​必须卸载​​await​​函数中
  • ​await​​​右侧的表达式一般是​​promise​​对象
  • ​await​​​返回的是​​promise​​成功的值
  • 如果​​await​​​的​​promise​​​失败了,就会抛出异常,需要通过​​try...catch​​来捕获处理
async function process(array) {
for await (let i of array) {
doSomething(i);
}
}

3.2 Object.values 和 Object.entries

  • ​Object.values()​​方法返回一个给定对象的所有可枚举属性值的数组
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']
  • ​Object.entries()​​​方法返回一个给定对象自身可遍历属性​​[key,value]​​ 的数组
const obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]

3.3 Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象,如果没有任何自身属性,则返回空对象。

【JavaScript】ECMASript 6—10新增常用知识汇总_字符串_03

3.4 String padding

在ES8中String新增了两个实例函数​​String.prototype.padStart​​​和​​String.prototype.padEnd​​,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。

(1)头部插入:String.prototype.padStart

用法:​​String.padStart(targetLength,[padString])​

  • targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
  • padString:(可选)填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,此参数的缺省值为 " "。
console.log('2'.padStart(4,'12345')) //1232

(2)结尾插入:String.prototype.padEnd

用法:​​String.padEnd(targetLength,padString])​

  • targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
  • padString:(可选) 填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,此参数的缺省值为 " ";
console.log('2'.padEnd(4,'12345'))  //2123

4. ECMASript 9(2018)

4.1 Rest/Spread 属性

在ES6中引入了Rest 参数与 spread 扩展运算符,但是他们只针对数组,在ES9中为对象也提供了相同的属性。

const obj = {
a: 1,
b: 2,
c: 3
};

const { a, ...x } = obj;
// 作为函数参数
function obj({ a, ...x }) {
console.log(a) // 1
console.log(x) // {b: 2, c: 3}
}

// 拷贝对象
const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { ...obj1, z: 4 }; // { a: 1, b: 2, c: 3, z: 4 }

4.2 Promise.finally()

使用Promise调用,成功会触发​​.then()​​​,失败会触发​​.catch()​​​。在有些情况下,如果我们想要在无论Promise成功还是失败情况下运行相同的代码,例如清除,删除对话,关数据库连接等,就可以使用​​.finally()​​来完成需要的逻辑。

function doSomething() {
doSomething1()
.then(doSomething2)
.then(doSomething3)
.catch(err => {
console.log(err);
})
.finally(() => {
// finish here!
});
}

4.3 正则表达式命名捕获组

ES9 允许命名捕获组使用符号 ​​?<name>​​,这样获取捕获结果可读性更强

const reDate = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/,
match = reDate.exec('2020-05-20'),
year = match.groups.year, // 2020
month = match.groups.month, // 05
day = match.groups.day; // 20

如果匹配失败,就会返回undefined

4.4 正则表达式反向断言

ES9 的正则表达式支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。

  • “反向断言”指的是 x只有在y后面才匹配,必须写成​​/(?<=y)x/​​。比如,只匹配美元符号之后的数字:
/(?<=\$)\d+/.exec('$100'); // ["100", index: 1, input: "$100", groups: undefined]
  • “否定反向断言”指的是 x只有不在y后面才匹配,必须写成​​/(?<!y)x/​​。比如,只匹配不在美元符号后面的数字:
/(?<!\$)\d+/.exec('€100'); // ["100", index: 2, input: " €100", groups: undefined]

4.5 正则表达式的dotAll模式

正则表达式中点​​.​​匹配除回车外的任何单字符,标记s改变这种行为,允许行终止符的出现,例如:

/hello.world/.test('hello\nworld');  // false
/hello.world/s.test('hello\nworld'); // true

5. ECMASript 10(2019)

5.1 flat()、flatMap()

(1)Array.prototype.flat()

该方法可以按照指定的深度递归遍历数组,并将所有的元素与遍历到的子数组中的元素合并为一个新的数组。

  • flat()方法的一大作用就是将数组降维( 数组扁平化)
var arr1 = [1, 2, [3, 4, [5, 6]]];
arr1.flat(); // [1, 2, 3, 4, [5, 6]]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(2); // [1, 2, 3, 4, 5, 6]

递归的深度默认为1,可以使用​​Infinity​​来递归任意的深度。

  • 除了可以用来扁平化数组之外,还可以用来清空数组的空项:
var arr = [1, 2, 3, , 5];
arr.flat(); // [1, 2, 3, 5]

(2)Array.prototype.flatMap()

​flatMap()​​​方法首先使用映射函数映射每个元素,然后将结果放在一个数组中。和​​map()​​方法类似。

var arr = [1, 2, 3, 4];

arr.map(x => [x * 2]); // [[2], [4], [6], [8]]

arr.flatMap(x => [x * 2]); // [2, 4, 6, 8]

​flatMap()​​​方法对原数组的每个成员执行一个函数,相当于执行​​Array.prototype.map()​​​,然后对返回值组成的数组执行​​flat()​​​方法。该方法返回一个新数组,不改变原数组。但是​​flatMap()​​方法只能展开一层数组。

var arr = [1, 2, [3, 4, [5, 6]]];
var res = arr.flatMap(x => [x * 2])
console.log(res) // [2, 4, NaN]

5.2 trimStart()、trimEnd()

这两个方法用来去除字符串首尾的空白字符。

在ES5中有类似的方法:​​trim()​​,该方法是去除字符串的首尾的空白字符。

5.3 Object.fromEntries()

在ES2018中新增了​​Object.entries()​​​方法,该方法是返回一个对象自身可枚举属性的键值对数组,其排列与使用​​for...in​​ 循环遍历该对象时返回的顺序一致。

而 ​​Object.fromEntries()​​​相当于​​Object.entries()​​方法的反转。

该方法传入一个键值对的列表,并返回一个带有这些键值对的新对象。

  • 将map转化为对象
const map = new Map([ ['foo', 'bar'], ['baz', 42] ]);
const obj = Object.fromEntries(map);
console.log(obj); // { foo: "bar", baz: 42 }
  • 将数组转化为对象
const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ];
const obj = Object.fromEntries(arr);
console.log(obj); // { 0: "a", 1: "b", 2: "c" }

5.4 Function.prototype.toString()

toString() 方法返回一个表示当前函数源代码的字符串,包括空格是注释

5.5 基本数据类型BigInt

现在的基本数据类型有七种n,分别是: String、Number、Boolean、Null、Undefined、Symbol、BigInt