ECMAScript学习笔记


ES6 基础类型

let

1 .变量不能重复声明

2 .块级作用域

3 .不存在变量提升

4 .不影响作用域链

const 定义常量

1 .一定要赋初始值

2 .一般常量使用大写

3 .常量的值不能修改

4 .块级作用域

5 .对于数组和对象元素修改,不算对常量的修改,不会报错

1
2
const TEAM = ['UZI','Ming','Kasa'];
TEAM.push('Lifa');//控制台不会报错,因为常量指向的地址没有发生改变,虽然数组元素改变了

变量的解析赋值

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

1 .数组的解构

1
2
3
const jijie = ["春", "夏", "秋", "冬"];
let [a, b, c, d] = jijie;
console.log(a, b, c, d);

2 .对象的解构

1
2
3
4
5
6
7
8
9
10
11
12
const obj = {
name: "张三",
age: 18,
fn: function () {
console.log("testtest");
},
};
let { name, age, fn } = obj;
console.log(name);
console.log(age);
console.log(fn);
fn();

模板字符串

ES6 引入新的声明字符串的方式

特性:

  • 内容可以直接出现换行符
  • 变量可以直接拼接 ${}
1
2
3
let fistName = "Lee";
let fullName = `${fistName}Alfa`;
console.log(fullName);

简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法,这样更简洁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let objName = "lifa";
let funTest = function () {
console.log("fnTest");
};
// let objSimplify={
// objName:objName,
// funTest:funTest,
// anotherFn:function(){
// console.log('another');
// }
// }
let objSimplify = {
objName,
funTest,
another(){
console.log(another);
}
};
console.log(objSimplify);

箭头函数

ES6 允许使用箭头(=>)定义函数

特性:

1 .this 是静态的,this 始终指向函数声明时所在作用域下的 this 的值,即便是 call 也不可改变 this 的指向

2 .不能作为构造函数实例化对象

3 .不能使用 arguments 对象

4 .箭头函数简写

  • 省略小括号,当形参有且只有一个的时候

  • 省略花括号,当代码体只有一条语句的时候,此时 return 必须省略,而且语句执行的结果就是函数的返回值

箭头函数适合与 this 无关的回调,定时器,数组的方法回调

箭头函数不适合与 this 有关的回调,事件回调,对象的方法

参数默认值

ES6 允许给函数参数赋值初始值

1 .形参初始值,具有默认值的参数,一般位置要靠后(潜规则)

2 .与解构赋值结合

1
2
3
4
5
6
7
8
9
10
11
12
function connect({ url = "127.0.0.1", host, username, port }) {
console.log(url);
console.log(host);
console.log(username);
console.log(port);
}
connect({
host: "atguigu.com",
username: "root",
password: "root",
port: 3306,
});

rest 参数

ES6 引入rest参数,用于获取函数的实参,用来替代 arguments,arguments 不是数组,而 rest 是数组

注意:rest 参数必须要放到参数最后

1
2
3
4
5
6
7
8
9
10
11
//ES5获取参数方式
function date1() {
console.log(arguments);
}
date1("a", "b", "c", typeof arguments);//[Arguments] { '0': 'a', '1': 'b', '2': 'c', '3': 'object' }
//ES6方式
function date2(a, b, ...rest) {
console.log(rest);
}
date2("aa", "bb", "cc", "dd");//[ 'cc', 'dd' ]

spread 扩展运算符

…扩展运算符能将数组(或伪数组)**转换为逗号分隔的参数序列**

1
2
3
4
5
6
const dir = ['东','南','西','北'];
function dirFn(){
console.log(arguments);
}
dirFn(dir);//[Arguments] { '0': [ '东', '南', '西', '北' ] }
dirFn(...dir);//[Arguments] { '0': '东', '1': '南', '2': '西', '3': '北' }

应用:

  • 数组合并
1
2
3
4
5
6
const arr1 = ["a", "b"];
const arr2 = ["c", "d"];
const fullArr1 = arr1.concat(arr2); //[ 'a', 'b', 'c', 'd' ]
console.log(fullArr1);
const fullArr2 = [...arr1, ...arr2]; //[ 'a', 'b', 'c', 'd' ]
console.log(fullArr2);
  • 数组克隆

  • 将伪数组转换为真数组

1
2
3
4
5
function spreadFn() {
console.log(arguments);//[Arguments] { '0': 'a', '1': 'b' }
console.log([...arguments]);//[ 'a', 'b' ]
}
spreadFn("a", "b");

Symbol

原始数据类型 Symbol,表示独一无二的值,第七种数据类型

  • Symbol 特点

    • Symbol 的值是唯一的,用来解决命名冲突的问题
    • Symbol 值不能与其他数据进行运算
    • Symbol 定义的对象属性不能用 for…in 循环遍历,但可以使用 Reflect.ownKeys 来获取对象的所有键名
  • 创建 Symbol

  1. Symbol()方式
1
2
3
4
5
let s = Symbol();
console.log(s, typeof s);
let s1 = Symbol("我是描述字符串");
let s2 = Symbol("我是描述字符串");
console.log(s1 == s2); //false
  1. 使用 Symbol.for 创建
1
2
3
4
5
6
7
let s3 = Symbol.for("尚硅谷");
let s4 = Symbol.for("尚硅谷");
let s5 = Symbol.for("我是描述字符串");
console.log(s3, typeof s3);
console.log(s3 == s4);//true
console.log(s3 === s4);//true
console.log(s3 == s5);//false
  • 七种数据类型

USONB–you are so niubility
u undefined

s——string symbol

o——object

n——null number

b——boolean

Symbol 创建对象属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  let game = {
up: function () {
console.log("upup");
},
down: function () {
console.log(down);
},
[Symbol("left")]: function () {//此种方法如何调用?
console.log("left1");
},
[Symbol.for('left')]: function () {//此种方法可以调用
console.log("left2");
},
};
// console.log(game[Symbol("left")]);
------------------------------------------------------------------
let methods = {
up: Symbol("up"),
down: Symbol("down"),
left: Symbol("left"),
};
game[methods.up] = function () {
console.log("up2");
};
game[methods.down] = function () {
console.log(down2);
};
game[methods.left] = function () {
console.log("left3");
};
console.log(game);
// console.log(game[Symbol('left')]());
console.log(game[Symbol.for('left')]());

Symbol 内置值

11 个内置的 Symbol 值,指向语言内部使用的方法,控制对象在特定场景下的表现

  • Symbol.hasInstance
1
2
3
4
5
6
7
8
9
10
class Persong {
static [Symbol.hasInstance](param) {
console.log(param);
console.log("用来检测类型");
// return true;
return false;
}
}
let o = {};
console.log(o instanceof Persong);
  • Symbol.isConcatSpreadable
1
2
3
4
let symArr1 = ["1", "2"];
let symArr2 = ["3", "4", "5"];
symArr2[Symbol.isConcatSpreadable] = false;
console.log(symArr1.concat(symArr2));//["1", "2", Array(3)]

迭代器

迭代器(Iterator)是一个接口,任何数据结构只要部署了Iterator 接口(即对象中的属性,Symbol.iterator),就可以完成遍历操作。

  • ES6 创造的新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费。(for…in 遍历键名,for…of 遍历键值)

  • 原生具备 iterator 接口的数据(可用 for…of):Array 、Arguments、Set、Map、String、TypedArray、NodeList

  • 工作原理

    • 创建一个指针对象,指向当前数据结构的起始位置
      avatar

    • 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员

      avatar

    • 接下来不断调用 next 方法,指针一直往后移动,知道指向最有一个成员

    • 每次调用 next 方法返回一个包含 value 和 done 属性的对象

1
2
3
4
5
6
7
8
9
10
11
12
let iteratorArr = ['a', 'b', 'c'];
console.log(iteratorArr);
//获取Symbol.iterator对应的函数,用以创建对象,在可遍历对象的_proto_上
let iteratorFunction = iteratorArr[Symbol.iterator];
//创建指针对象,使用Symbol.iterator对应的函数创建
let iteratorObj = iteratorArr[Symbol.iterator]();
console.log(iteratorObj);
//指针对象上有next方法,调用
console.log(iteratorObj.next());//{value: "a", done: false}
console.log(iteratorObj.next());
console.log(iteratorObj.next());
console.log(iteratorObj.next());//{value: undefined, done: true}

自定义迭代器遍历对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const iteratorData = {
name: "二班",
students: ["老二", "雅兴", "张超"],
[Symbol.iterator]: function () {
let index = 0;
let _this = this;
return {
next: function () {
if (index < _this.students.length) {
const result = { value: _this.students[index], done: false };
index++;
return result;
} else {
const result = { value: _this.students[index], done: true };
return result;
}
},
};
},
};
for (let v of iteratorData) {
console.log(v);
}

生成器

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

  • 迭代器对象信息
    avatar
1
2
3
4
5
6
7
8
9
10
11
12
function* gen() {
yield "aaa";
yield "bbb";
yield "ccc";
}
let iteratorGen = gen();//返回值为一个迭代器对象
console.log(iteratorGen);
console.log(iteratorGen.next()); //{value: "aaa", done: false}

for (const v of gen()) {
console.log(v); //aaa bbb ccc
}

生成器函数参数

  • 函数传参和 next 方法传参,两种方式
  • 第一个 next 方法传递的参数不可输出,第二个 next 方法参数将作为第一个 yield 返回结果值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function* gen2(arg){
console.log(arg);//AAA
let one = yield '111';
console.log(one);//BBB
let two = yield '222';
console.log(two);//CCC
let three = yield '333'
console.log(three);
}
//执行获取迭代器对象
let paramGen = gen2("AAA");
console.log(paramGen.next('EEE'));//无输出
console.log(paramGen.next('BBB'));//next方法可以传入参数,BBB作为第一个yield返回结果
console.log(paramGen.next('CCC'));//CCC将作为第二个yield返回结果
console.log(paramGen.next('DDD'));

生成器实例

1 .回调地狱问题

  • js 异步编程 文件操作 网络操作 数据库操作
  • 解决回调地狱问题
    • 将异步任务放到 yield 语句后执行,调用 next 方法执行 yield 语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function one(){
setTimeout(() => {
console.log(111);
iteratorHell.next();
}, 1000);
}
function two(params) {
setTimeout(() => {
console.log(222);
iteratorHell.next();
}, 2000);
}
function three(params) {
setTimeout(() => {
console.log(333);
// iterator.next();
}, 3000);
}
function* dealHellFun(params) {
yield one();
yield two();
yield three();
}
let iteratorHell = dealHellFun();
iteratorHell.next();

2 .模拟数据获取 用户数据 订单数据 商品数据

  • 数据是有关联的,要先有用户,根据用户获取订单,在获取商品数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function getUser(params) {
setTimeout(() => {
let data = '用户数据';
iteratorMall.next(data);//第二次调用next,传入的参数做为第一个yield语句返回结果
}, 1000);
}
function getOrders(params) {
setTimeout(() => {
let data = '订单数据';
iteratorMall.next(data);
}, 1000);
}
function getGoods(params) {
setTimeout(() => {
let data = '商品数据';
iteratorMall.next(data);
}, 1000);
}
function* gen3(){
let user = yield getUser();
console.log(user);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
let iteratorMall = gen3();
iteratorMall.next();

Promise 基本语法

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

  • Promise 构造函数:Promise(excutor){}

  • Promise.prototype.then 方法

  • Promise.prototype.catch 方法

  1. Promise 封装 Ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let p = new Promise((resolve, reject) => {
//1.创建对象
let xhr = new XMLHttpRequest();
//2.初始化
xhr.open("get", "https://api.apiopen.top/getJoke");
//3.发送
xhr.send();
//4.绑定事件,处理相应结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
}
}
};
});
p.then(value => {
console.log(value);
}).catch(err => {
console.log(err);
});
  1. Promise 的 then 方法
  • then 方法的返回结果也是 Promise 对象,对象状态由回调函数执行结果决定

    • 如果 then 方法回调函数中返回的结果是非 Promise 类型的属性,then 返回的 promise 对象的状态为成功,返回值为对象的成功的值(即 resolve 函数传入的值)

    • 如果 then 方法回调函数中返回结果是Promise 对象,then 返回的 promise 对象的状态为返回的 promise 对象的状态,返回值为返回的 promise 对象 then 方法返回的值(resolve 函数参数的值)

    • 如果 then 方法回调函数中返回结果是抛出错误,then 返回的 promise 对象的状态为 rejected,返回值为抛出错误的值

  • then 方法可以链式调用

1
p.then(success=>{},err=>{}).then()
  • 读取多个文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var fs = require("fs");
const { resolve } = require("path");
var readPromise = new Promise((resolve, reject) => {
fs.readFile("./data/readfile1.txt", function (err, data1) {
// console.log(data1.toString());
resolve(data1);
});
});
readPromise
.then((value) => {
return new Promise((resolve, reject) => {
fs.readFile("./data/readfile2.txt", function (err, data2) {
resolve([value, data2]);
});
});
})
.then((value) => {
fs.readFile("./data/readfile3.txt", function (err, data3) {
value.push(data3);
console.log(value.join("\r\n"));
});
});

Set

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

1 .集合的属性和方法:

  • size 返回集合的元素个数
  • add 增加一个新元素,返回当前集合
  • delete 删除元素,返回 bool 值
  • has 检测集合中是否包含某个元素,返回 bool 值
  • clear 清空集合

2 .应用

  • 数组去重
1
2
3
let setArr1 = [1,2,3,4,5,4,3,2,1];
let newArr1 = [...new Set(setArr1)];
console.log(newArr1);
  • 交集
1
2
3
4
5
let setArr2 = [4,5,6,5,4];
let unionArr = [...new Set(setArr1)].filter(item=>{
return new Set(setArr2).has(item);
})
console.log(unionArr);
  • 并集
1
2
let result = [...new Set([...setArr1,...setArr2])];
console.log(result);
  • 差集
1
2
3
4
let diffArr = [...new Set(setArr1)].filter(item => !(new Set(setArr2).has(item)));
console.log(diffArr);//[ 1, 2, 3 ]
let diffArr2 = [...new Set(setArr2)].filter(item=>new Set(setArr1).has(item));
console.log(diffArr2);

Map

ES6 提供了 Map 数据结构。

  • 类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种各类型的值(包括对象)都可以当做键。
  • Map 也实现了 iterator 接口,所以可以使用扩展运算符和 for…of 进行遍历

Map 的属性和方法:

  • size 返回 Map 元素的个数
  • set 增加一个新元素,返回当前 Map
  • get 返回简明对象的键值
  • has 检测 Map 中是否包含某个元素,返回 bool 值
  • clear 清空结合,返回 undefined

class 类

作为对象模板,通过 class 关键字,可以定义类。

  • 基本上,ES6 的 class 可以看做知识一个语法糖,他的绝大部分功能,ES5 都可以做到。
  • 新的 class 写法只是让对象原型的写法更加清晰、更像面向对象的语法而已。
  1. 类定义
  • 构造方法,名字必须为 constructor,不可修改
  • 方法必须使用 ES6 方法,不能使用 ES5 的对象完整形式
1
2
3
4
5
6
7
8
9
10
11
class Phone {
constructor(brand, price) {
this.brand = brand,
this.price = price;
}
call(){
console.log('打电话');
}
}
let phone = new Phone('Iphone','5毛');
console.log(phone);
  1. class 静态成员

函数是一个对象,[函数名]为函数对象;[new 函数名]获得的对象是实例对象

属于函数对象而不属于实例对象的属性和方法,称之为静态成员。则静态成员属于类不属于实例对象

  1. ES5 方式实例对象
  • 实例对象和函数对象是不同的,属性和方法是不通的
1
2
3
4
5
6
7
8
9
10
11
//MPhone是函数对象,mPhone是实例对象
function MPhone(){

}
MPhone.name = '小米';
MPhone.call = function(){
console.log('Hello mi fans');
}
let mPhone= new MPhone();
//对象上没有构造函数上的属性方法
console.log(mPhone.name);//undefined
  • 实例对象和构造函数原型对象是相通的
1
2
3
4
5
6
7
8
9
function MPhone(){

}
MPhone.prototype.name = '小米';//给构造函数上添加属性
MPhone.prototype.call = function(){
console.log('Hello mi fans');
}
let mPhone= new MPhone();
console.log(mPhone.name);//小米
  1. ES6 中 class 静态成员

静态成员属于类不属于实例对象

1
2
3
4
5
6
7
8
9
 class StaticPhone{
static name = 'shouji';
static change(){
console.log('static方法');
}
}
let nokia = new StaticPhone();
console.log(nokia.name);//undefined
console.log(StaticPhone.name);//手机
  1. 对象继承
  • ES5 使用构造函数实现对象继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//父级
function MPhone(brand, price) {
this.brand = brand;
this.price = price;
}
MPhone.prototype.call3 = function () {
console.log("打电话");
};
//子级
function SmartPhone(brand, price, color, size) {
//调用父级构造函数初始化代码,避免代码重写
MPhone.call(this, brand, price);
this.color = color;
this.size = size;
}
//设置子级构造函数原型
SmartPhone.prototype = new MPhone(); //实例对象和构造函数原型上的属性方法是相通的
SmartPhone.prototype.constructor = SmartPhone;
//声明子级的方法(注意:实例上并不会出现此方法)
SmartPhone.photo1 = function () {
console.log("函数对象(父级)方法");
};
//声明子级实例的方法
SmartPhone.prototype.photo = function () {
console.log("实例对象(子级)方法");
};
//实例化
const hammer = new SmartPhone("锤子", 3333, "黑色", "5inch");
console.log(hammer);

avatar

  • ES6 中 class 对象继承

    • 继承方式:class 子类名 extends 父类名{}
    • 子类中添加 super()函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class FatherClass {
constructor(brand, price) {
this.brand = brand;
this.price = price;
}
call3() {
console.log('class父级方法');
}
}
class SonClass extends FatherClass {
constructor(brand, price, color, size) {
super(brand, price);
this.color = color;
this.size = size;
}
sonFun() {
console.log('子类的方法');
}
}
let sonClass = new SonClass('iPhone', 333, '星空灰', '4inch');
console.log(sonClass);

avatar

  1. 子类对父类方法的重写
  • 子类不可以直接调用父类同名方法,super 方法只能出现在 constructor
  1. class 中 getter 和 setter
  • get 通常对对象的动态属性进行封装
  • set 添加更多的控制
1
2
3
4
5
6
7
8
9
10
11
12
class GetSetClass {
get price() {
console.log('获取价格');
return 'huoqu'
}
set price(newVal) {
console.log('价格修改');
}
}
let getSetClass = new GetSetClass();
console.log(getSetClass.price);
getSetClass.price = '124'

数值扩展

  1. Number.EPSILON 是 JavaScript 表示的最小精度,接近 2.22E-16

  2. 二进制和八进制

    • 二进制 0b 开头,八进制 0o 开头,十六进制 ox 开头
  3. Number.isFinite 检测一个数值是否为有限数

  4. Number.inNaN 检测一个数值是否为有限数

  5. Number.parsInt Number.parseFloat 字符串转换

  6. Number.isInteger 判断一个数是否为整数

  7. Math.trunc 将数字的小鼠部分抹掉

  8. Math.sign 判断一个数到底为正数 负数 还是零

对象方法扩展

  1. Object.is 判断两个值是否完全相等
1
2
console.log(NaN===NaN);//false
console.log(Object.is(NaN,NaN));//true
  1. Object.assign 对象的合并

  2. Object.setPrototypeof 设置原型对象 Object.getPrototypeof

ES6 模块化

模块化是将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来.

优点:

  • 防止命名冲突
  • 代码复用
  • 高维护性

模块化规范产品

  • CommonJS—>Node Browserify
  • AMD —> requireJS
  • CMD —> seaJS
  • ES6 规范 —> 浏览器端规范

ES6 模块化语法

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

  • export 命令用于规定模块的对外接口
  • import 命令 用于输入其他模块提供的功能(html 中引入时要设置 script 标签的 type 属性为 module)

一、export 暴露方式:

  1. 分别暴露
1
2
3
4
export let name1 = '分别暴露方式';
export function exportFun1(){
console.log('分别暴露方式函数');
}

avatar

  1. 统一暴露
1
2
3
4
5
6
let name1 = '分别暴露方式2';
function exportFun1(){
console.log('分别暴露方式函数2');
}

export {name1,exportFun1}

avatar

  1. 默认暴露
1
2
3
4
5
6
export default {
name1: "default暴露方式",
exportFun1: function () {
console.log("default暴露方式");
},
};

avatar

二、引入模块

  1. 通用导入
1
import * as m1 from './js/export1.js'//通用的引入方式
  1. 解构赋值形式
1
2
3
4
5
6
7
8
//分别导出的引入
import {name1,exportFun1} from './js/export1.js'//解构赋值方式

//统一导出的引入
import {name1 as name,exportFun1 as fun} from './js/export2.js'//设置别名解决命名冲突

//default导出的引入
import {default as m3} from './js/export3.js'
  1. 简便形式,只能针对默认暴露
1
import m4 from './js/export3.js'//简便形式,只适合default导出的

ES6-浏览器使用 ES6 模块化方式

  1. 直接导入方式

  2. –>app.js 方式

在 app.js 文件引入各个模块文件,然后在 html 文件中引入 app.js 文件

1
2
3
4
5
6
7
8
9
10
app.js
import * as m1 from './export1.js'//通用的引入方式
import { name1 as name, exportFun1 as fun } from './export2.js'
import { default as m3 } from './export3.js'
import m4 from './export3.js'//简便形式,只适合default导出的

console.log(m1);
console.log(name);
console.log(m3);
console.log(m4);
  1. –>Babel 方式(ES6→ES5)
  • 并非所有的浏览器支持 ES6 语法
  • ES6 模块化还不能对 npm 安装的模块进行导入

步骤:

  1. 安装工具 babel-cli(babel 命令行工具)、 babel-preset-env(预设包,把最新的 ES 特性转换为 ES5)、 browserify(webpack)

  2. 语法转换 npx babel 源文件目录 -d dist/js –preset=babel-preset-env

    • ES6 语法转换为 CommonJS 模块规范化语法
    • 浏览器不识别 require 语法
  3. 打包 npx browserify dist/js -o dist/bundle.js

ECMAScript7 新特性

  1. Array.prototype.includes

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

  2. 指数运算符

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

ECMAScript8 新特性

async 和 await 两种语法相结合可以让异步代码像同步代码一样

  1. async 函数
  • async 函数的返回值为 promise 对象,此对象由此函数内部 return 的状态决定
  • promise 对象的结果由 async 函数执行的返回结果决定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function asyncTest() {
//返回结果不是一个promise类型的对象,返回的结果就是成功Promise对象
// return;//状态成功
//返回一个字符串
// return 'async函数';//状态成功
//抛出错误,返回的结果是一个失败的Promise
// throw new Error('出错啦');//状态失败
return new Promise((resolve, reject) => {
// resolve('状态成功');//指此promise对象状态成功,则async函数状态成功
reject("状态失败");//意味着此promise对象状态失败,则async函数状态失败
});
}
let asyncResult = asyncTest();
console.log(asyncResult);
  1. await 表达式
  • await 必须写在 async 函数中
  • await 右侧的表达式一般为 promise 对象
  • await 返回的是 promise 对象成功的值
  • await 的 promise 失败了,就会抛出异常,需要通过 try…catch 捕获处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let awaitPromise = new Promise((resolve, reject) => {
// resolve('await后面一般为promise对象');
reject('失败');
});
//await函数写在async中
async function awaitFun() {
try {
let result = await awaitPromise;
console.log('await返回的是promise对象成功的值:');
console.log(result);
} catch (error) {
console.log(error);
}
}
awaitFun();
  1. async 和 await 集合读取文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const fs = require("fs");
function getFile1() {
return new Promise((resolve, reject) => {
fs.readFile("./data/readfile1.txt", function (err, data1) {
// console.log(data1.toString());
if(err) reject(err)
resolve(data1);
});
});
}
function getFile2() {
return new Promise((resolve, reject) => {
fs.readFile("./data/readfile2.txt", function (err, data1) {
// console.log(data1.toString());
if(err) reject(err)
resolve(data1);
});
});
};
function getFile3() {
return new Promise((resolve, reject) => {
fs.readFile("./data/readfile3.txt", function (err, data1) {
// console.log(data1.toString());
if(err) reject(err)
resolve(data1);
});
});
}
async function getAllContent() {
let data1 = await getFile1();
let data2 = await getFile2();
let data3 = await getFile3();

console.log(data1.toString());
console.log(data2.toString());
console.log(data3.toString());
}
getAllContent();
  1. async 和 await 结合封装 Ajax
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function getData() {
return new Promise((resolve, reject) => {
// var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
//1.创建对象
let xhr = new XMLHttpRequest();
//2.初始化
xhr.open("GET", "https://api.apiopen.top/getJoke");
//3.发送
xhr.send();
//4.绑定事件,处理相应结果
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject();
}
}
};
});
}
//promise then 方式
// getData().then(value=>{console.log(value);},reason=>{
// console.log(reason);
// });
async function main() {
let result = await getData();
console.log(result);
}
main();

ES8 对象方法扩展

  1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组

  2. Object.entries()方法返回一个给定对象自身可遍历属性[key,value]的数组

  3. Object.getOwnPropertyDescriptors()方法返回指定对象所有自身属性的描述对象

1
2
3
4
5
6
7
8
9
10
const es8Obj = {
url:'2.2.2.2',
method:'get',
host:'localhost'
}
console.log(Object.keys(es8Obj));
console.log(Object.values(es8Obj));
console.log(Object.entries(es8Obj));
console.log(Object.getOwnPropertyDescriptors(es8Obj));

ES9 扩展运算符与 rest 参数

  • Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对数组。
  • 在 ES9 在为对象提供了像数组一样的 rest 参数和扩展运算符

ES9 正则扩展

命名捕获分组

1
2
3
4
5
6
7
8
9
10
11
12
13
let url = '<a href="https:baidu.com">百度</a>';
let reg = /<a href="(.*)">(.*)<\/a>/;
let result = reg.exec(url);
console.log(result);
console.log(result[0]);
console.log(result[1]);
console.log(result[2]);

let reg2 = /<a href="(?<str>.*)">(?<name>.*)<\/a>/;
let result2 = reg2.exec(url);
console.log(result2);
console.log(result2.groups.str);
console.log(result2[1]);

avatar

avatar

反向断言

根据目标前后内容做唯一性识别

1
2
3
4
5
6
7
8
let str = "JS1234你知道么555啦啦啦";//匹配555
let reg = /\d+(?=啦)/;
let result = reg.exec(str);
console.log(result);//555

//反向断言
let reg2 = /(?<=么)\d+/
console.log(reg2.exec(str));//555

dotAll 模式

dot . 元字符–>匹配处换行符之外的任意字符

dotAll 模式使.可以匹配任意字符

ES10

Object.fromEntries

  • 传入二维数组,创建对象
1
2
3
let arr = [['a','es10学习'],['b','es10对象扩展']];
let es10Obj = Object.fromEntries(arr);
console.log(es10Obj);//{ a: 'es10学习', b: 'es10对象扩展' }
  • 传入 Map
1
2
3
4
5
6
let map = new Map();
map.set("name", "aaa");
let e = Object.fromEntries(map);
console.log(e); //{name:'aaa'}
//fromEntries与entries逆操作
console.log(Object.entries(e)); //['name','aaa']

trimStart 与 trimEnd

用以清除字符前后的空白

flat 与 flatMap

数组的两个方法

  • flat 将多为数组转换为低维数组,参数为整数,表示深度,默认值为 1
  • flatMap()数组的方法,与 Array.map 类似,可以将遍历的 item 返回的结果降低维度

Symbol.prototype.description

获取 Symbol 函数参数值

ES11

私有属性

对属性的封装,私有属性用“#”标识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person{
//公有属性
name;
//私有属性
#age;
#weight;
constructor(name,age,weight){
this.name = name;
this.#age = age;
this.#weight = weight;
}
intro(){
console.log(this.#age);
}
}
let person = new Person('aa',13,22)
console.log(person.intro());
// console.log(person.#age);//报错

Promise 批处理方法

  1. Promise.allSettled()
  • 接收 Promise 数组,返回 Promise 对象
  • 返回的结果永远是成功的状态,结果为每一个 promise 状态和结果值
  1. Promise.all()
  • 接收 Promise 数组
  • 返回结果由数组中每一个 promise 状态决定,全成功才成功

字符串扩展方法 matchAll

String.prototype.matchAll 用来得到正则批量匹配得到的结果

可选链操作符

  • 形式:?.的组合

  • 对象类型参数层级比较深,此符号可避免层层判断

动态 import

实现按需加载

import()函数,传入资源路径,返回结果为 promise 对象

BigInt

用于大整数数值运算

  • 在普通数字后加一个 n 即为大整型
  • 转换为此类型方法 BigInt(),只能传入整数
  • 不能与普通整数做运算,需要把普通整数转换为 BigInt 类型

globalThis

全局的 this,始终指向全局对象


文章作者: AlfaLee
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AlfaLee !
  目录