1 es6新特性
1.1 let 关键字
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
- 不允许重复声明
- 块儿级作用域
- 不存在变量提升
- 不影响作用域链
应用场景:以后声明变量使用 let 就对了
1.2 const关键字
const关键字用来声明常量,const声明有以下特点
- 声明必须赋初始值
- 标识符一般为大写
- 不允许重复声明
- 值不允许修改
- 块儿级作用域
- 注意:对象属性修改和数组元素变化不会触发const错误,因为地址没有改变
应用场景:声明对象类型使用const,非对象类型声明选择let
1.3 变量的解构赋值
1.4 模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
- 可以使用 ${xxx} 形式输出变量
1.5 简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let zh = {
// improve: function(){
// console.log(111);
// }
// 简写形式
improve(){
console.log(111);
}
}
1.6 箭头函数
ES6 允许使用「箭头」(=>)定义函数。
箭头函数的注意点:
-
如果形参只有一个,则小括号可以省略
-
函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果,return必须省略
-
箭头函数 this 指向声明时所在作用域下 this 的值,并且this是静态的,调用call方法也不能改变
let jian1 = function(){ console.log(this.name); } let jian2 = () => { console.log(this.name); } let school = { name: '前台', } window.name = '尚硅谷' jian1() jian2() console.log('=================='); jian1.call(school) // 前台 jian2.call(school) //依然是尚硅谷 -
箭头函数不能作为构造器,构造函数,来实例化对象
let hh = (name, age) => { this.name = name, this.age = age } let zs = new hh() //会报错 -
不能使用 arguments
let zhao = () => {
console.log(arguments);// 报错,argument is not defined
}
zhao()
1.7 函数参数的默认值设置
1.允许给函数参数赋予默认初始值,并且通常放在后面
function ff(a, b, c=10){
return a + b + c
}
console.log(ff(1, 5));
2.与解构赋值结合使用
function ff({a, b, c=10}){
return a + b + c
}
console.log(ff({a: 1, b: 5}));
1.8 rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments,rest参数必须放到最后
function hu(){
console.log(arguments);
}
function zh(...args){
console.log(args);
}
hu(1,2,3,5,9) //对象
zh(1,2,3,5,9) //数组
1.9 扩展运算符
扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
1. 数组的合并
let a = ['zas', 'kjkj','kjkkas']
console.log(...a); // 结果 zas kjkj kjkkas
let b = ['咋还不干', '杂技']
let c = b.concat(a) //
let d = [...a, ...b]
console.log(c); // ['咋还不干', '杂技', 'zas', 'kjkj', 'kjkkas']
console.log(d); // ['zas', 'kjkj', 'kjkkas', '咋还不干', '杂技']
2. 数组拷贝 // 浅拷贝
let e = [...a]
console.log(e); //['zas', 'kjkj', 'kjkkas']
3. 将伪数组转为真正的数组
1.10 第七种数据类型symbol
八种数据类型:usonb(you are so nb) {undefined, string, symbol, object, number , null, boolean, bigint} ,NaN属于Number类型
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol 特点
- Symbol 的值是唯一的,用来解决命名冲突的问题
- Symbol 值不能与其他数据进行运算
- Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用Reflect.ownKeys 来获取对象的所有键名
let s = Symbol()
console.log(s, typeof s); // Symbol() 'symbol'
let s1 = Symbol('尚硅谷')
let s2 = Symbol('尚硅谷')
console.log(s1 === s2, s1); // false Symbol(尚硅谷)
let s3 = Symbol.for('山硅')
let s4 = Symbol.for('山硅')
// 不能与其他数据进行运算
console.log(s3 === s4, s3) // true Symbol(山硅)
s3 + 10 //报错
应用场景
// 向对象中添加方法
let school = {
up(){
console.log(111);
},
down(){
console.log(222);
}
}
// 第一种方式,声明一个对象
let set = {
up: Symbol(),
down: Symbol()
}
school[set.up] = function(){
console.log(1111);
}
school[set.down] = function(){
console.log(2222);
}
console.log(school); //up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}
// 第二种方式,直接用
let ss = {
name: 'as',
[Symbol('say')](){
console.log(111);
},
[Symbol('sy')](){
console.log(111);
}
}
console.log(ss); // {name: 'as', Symbol(say): ƒ, Symbol(sy): ƒ}
symbol 的内置属性
class Person {
static [Symbol.hasInstance](params){
console.log(params);
return false
}
}
let o = {}
console.log(o instanceof Person); // {} // false
const arr1 = [1,2,3]
const arr2 = [1,2,3]
arr2[Symbol.isConcatSpreadable] = false
console.log(arr2.concat(arr1)); //[Array(3), 1, 2, 3]
1.11 迭代器
迭代器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
-
ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费
-
原生具备 iterator 接口的数据(可用 for of 遍历)
- Array
- Arguments
- Set
- Map
- String
- TypedArray
- NodeList
工作原理
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
let arr = ['唐山', '按时', '不信', '回家']
for (const i in arr) {
console.log(i); // 0,1,2,3 输出的是索引
}
for (const i of arr) {
console.log(i); // '唐山', '按时', '不信', '回家'
}
let iterator = arr[Symbol.iterator]()
console.log(iterator.next()); //{value: '唐山', done: false}
需要自定义遍历数据的时候,要想到迭代器。
// 自定义迭代器
let arr = ['唐山', '按时', '不信', '回家'];
let school = {
name: '上回顾',
people: arr,
[Symbol.iterator]: function(){
let index = 0;
let that = this;
return {
next(){
if(index < that.people.length){
let result = {value: that.people[index], done: false}
index++
return result
}else{
return {value: undefined, done: true}
}
}
}
}
}
for (let i of school) {
console.log(i);
}
1.12 生成器函数
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
function * hhh(){
console.log(111);
yield 'qqqq',
console.log(222);
yield 'bbbb',
console.log(333);
yield 'cccc',
console.log(444);
yield 'ffff',
console.log(5555);
}
// 生成器函数调用不会直接执行,需要调用next()函数才会执行,并且,一次next()只会执行一段yield区域
let iterator = hhh()
iterator.next(); // 111
iterator.next(); // 222
iterator.next(); // 333
iterator.next(); // 444
console.log(iterator.next()); // {value: 'qqqq', done: false}
console.log(iterator.next()); // {value: 'bbbb', done: false}
// 生成器函数传参
function * hhh(aaa){
console.log(aaa);
let a1 = yield 'qqqq';
console.log(a1);
let a2 = yield 'bbbb';
console.log(a2);
let a3 = yield 'cccc';
console.log(a3);
}
let iterator = hhh('尚硅谷')
console.log(iterator.next('顺一块')) //尚硅谷 //{value: 'qqqq', done: false}
console.log(iterator.next('顺二块')) //顺二块 //{value: 'bbbb', done: false}
console.log(iterator.next('顺三块')) //顺三块 //{value: 'cccc', done: false}
console.log(iterator.next('顺四块')) //顺四块 //{value: undefined, done: true}
// 第二次next()传递的参数,作为第一个yield的返回结果
代码说明:
- *的位置没有限制
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到yield 语句后的值
- yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next方法,执行一段代码
- next 方法可以传递实参,作为 yield 语句的返回值
// 回调地狱问题
setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333);
}, 3000)
}, 2000)
}, 1000)
// 生成器函数解决方案
function one(){
setTimeout(()=>{
console.log(111);
iterator.next()
}, 1000)
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next()
}, 2000)
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next()
}, 3000)
}
function * hhh(){
yield one()
yield two()
yield three()
}
let iterator = hhh()
iterator.next()
// 生成器函数在异步任务中的应用
function getUsers(){
setTimeout(()=>{
let data = '用户信息';
iterator.next(data)
},1000)
}
function getOrders(){
setTimeout(()=>{
let data = '订单数据';
iterator.next(data)
},1000)
}
function getGoods(){
setTimeout(()=>{
let data = '商品数据';
iterator.next(data)
},1000)
}
function * Gen(){
let a = yield getUsers()
console.log(a);
let b = yield getOrders()
console.log(b);
let c = yield getGoods()
console.log(c);
}
let iterator = Gen()
iterator.next()
1.13 promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,
- 用来封装异步操作并可以获取其成功或失败的结果。
- Promise 构造函数: Promise (excutor) {}
- Promise.prototype.then 方法
- Promise.prototype.catch 方法
// promise的基本使用
let p = new Promise(function(resolve, reject){
setTimeout(()=>{
let data = '安徽是个好地方'
// resolve(data)
reject(data)
},1000)
})
// 当回调函数调用resolve,则then中执行第一个函数,reject则执行第二个函数
p.then(function(value){
console.log(value);
},function(reason){
console.error(reason);
})
// promise读取文件操作
// 正常方式
const fs = require('fs')
fs.readFile('../ES6/ES6_Promise/resources/为学.md', (err, res)=>{
if(err) {throw err}else{
console.log(res.toString());
}
})
// promise风格的写法
const p = new Promise(function(resolve, reject){
fs.readFile('../ES6/ES6_Promise/resources/为学.md2', (err, res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
p.then(function(valve){
console.log(valve.toString());
}, function(reason){
console.log(reason);
})
// promise封装AJAX请求
// 原生xhr发起请求
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://api.apiopen.top/getJoke');
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
} else {
console.log(xhr.status);
console.log('0000');
}
}
}
// promise风格发起请求
const p = new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest()
xhr.open("GET", "https://api.apiopen.top/getJoke");
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
} else {
reject(xhr);
}
}
}
})
p.then(function(value){
console.log(value);
}, function(reason){
console.log(reason);
})
// promise对象的返回结果
const p = new Promise(function (resolve, reject) {
setTimeout(() => {
let data = '转啊看见了'
// resolve(data)
reject(data)
}, 1000)
})
const result = p.then((value) => {
console.log(value);
},
(reason) => {
console.warn(reason);
})
console.log(result);
// then()的返回结果任然是promise对象,且返回对象的状态取决于then()中定义的函数的返回结果,
// 1. 如果返回结果为非promise对象,则result的状态为resolved(成功),且返回值为对象的成功值
// 2. 如果返回结果是promise对象,则返回的promise对象的状态即为result的状态(见result2的返回结果)
// 3. 如果返回结果是抛出错误,则返回结果的状态为失败,值为error的内容
const result1 = p.then((value) => {
console.log(value);
return '1111'
}, (reason) => {
console.warn(reason);
})
console.log(result1); // 返回值状态为成功,成功值为111
const result2 = p.then((value) => {
console.log(value);
return new Promise(function(resolve, reject){
resolve('data') // result2的状态为成功, 值为data
reject('data') // result2的状态为失败, 值为data
})
}, (reason) => {
console.warn(reason);
})
console.log(result1);
const result3 = p.then((value) => {
console.log(value);
throw 'error'
}, (reason) => {
console.warn(reason);
})
console.log(result1); // 返回值状态为失败,值为error
// 因此,then()方法可以链式调用,里面的函数也可以只写成功的回调
p.then(value => {}).then(value => {})
// 回调地狱小案例
const fs = require('fs')
// 回调地狱的一个问题就是变量名容易重复,且不易发现
fs.readFile('../ES6/ES6_Promise/resources/为学.md',(err, res1)=>{
fs.readFile('../ES6/ES6_Promise/resources/插秧诗.md',(err, res2)=>{
fs.readFile('../ES6/ES6_Promise/resources/观书有感.md',(err, res3)=>{
let data = res1 + '\n' + res2 + '\n' + res3
console.log(data);
})
})
})
const p1 = new Promise(function(resolve, reject){
fs.readFile('../ES6/ES6_Promise/resources/为学.md',(err, res1)=>{
resolve(res1)
})
})
p1.then((value)=>{
return new Promise(function(resolve, reject){
fs.readFile('../ES6/ES6_Promise/resources/插秧诗.md',(err, res1)=>{
resolve(res1 + '\n' + value)
})
})
}).then((value) =>{
return new Promise(function(resolve, reject){
fs.readFile('../ES6/ES6_Promise/resources/观书有感.md',(err, res1)=>{
resolve(res1 + '\n' + value)
})
})
}).then((value)=> {
console.log(value);
})
promise的catch()方法
const p = new Promise(function(resolve, reject){
fs.readFile('../ES6/ES6_Promise/resources/为学.md2', (err, res)=>{
if(err){
reject(err)
}else{
resolve(res)
}
})
})
// catch()只需要配置一个错误的函数即可
p.catch((error)=>{
console.log(error);
})
1.14 集合set(本质上也是对象)
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合
- delete 删除元素,返回 boolean 值
- has 检测集合中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回 undefined
let s = new Set(['爱上了肯德基', '奥斯卡缴费', '萨科技', '奥斯卡缴费'])
console.log(s); // {'爱上了肯德基', '奥斯卡缴费', '萨科技'}
// 集合的方法
console.log(s.size);
s.add('阿萨德')
console.log(s); // {'爱上了肯德基', '奥斯卡缴费', '萨科技', '阿萨德'}
s.delete('爱上了肯德基')
console.log(s); // {'奥斯卡缴费', '萨科技', '阿萨德'}
// s.clear() // 清空集合
console.log(s.has('阿萨德'));
for(let v of s){
console.log(v);
}
console.log(...s);
// set实践
let s = [1, 3 , 7, 8, 2, 1, 3]
// 数组去重
let s1 = [...new Set(s)]
console.log(s1);
// 交集
let arr = [8, 2, 1, 3, 5, 42, 86, 96]
let s2 = [...new Set(s)].filter((item)=>new Set(arr).has(item))
console.log(s2);
// 并集
let s3 = [...new Set([...s, ...arr])]
console.log(s3);
// 差集
let s4 = [...new Set(s)].filter(item=>!((new Set(arr)).has(item)))
console.log(s4);
1.15 Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。Map 的属性和方法:
- size 返回 Map 的元素个数
- set 增加一个新元素,返回当前 Map
- get 返回键名对象的键值
- has 检测 Map 中是否包含某个元素,返回 boolean 值
- clear 清空集合,返回 undefined
let a = new Map()
// 添加元素
a.set('name', '尚硅谷')
let b = {
name: '尚硅谷'
}
a.set(b, ['as', 'wjqd', 'qcs'])
console.log(a);
// size
console.log(a.size);
// 删除
// a.delete('name')
// console.log(a);
// 读取
console.log(a.get(b));
// 清空
// a.clear()
// 遍历
for(v of a){
console.log(v); // 遍历的结果是数组
}
1.16 class类
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
1. 知识点:
- class 声明类
- constructor 定义构造函数初始化
- extends 继承父类
- super 调用父级构造方法
- static 定义静态方法和属性
- 父类方法可以重写
// es5写法
function Phone(name, price) {
this.name = name
this.price = price
}
Phone.prototype.call = function () {
console.log('woshishouji');
}
let huawei = new Phone('huawei', 19)
console.log(huawei);
huawei.call()
// es6写法
class ShouJi {
constructor(name, price) {
this.name = name
this.price = price
}
call(){
console.log('woshishouji');
}
}
let huawei1 = new Phone('huawei', 19)
console.log(huawei);
huawei.call()
2.函数对象的属性和实例对象的属性是不相通的,实例对象和函数对象的原型对象是通的
function Phone() {
}
Phone.prototype.call = function () {
console.log('woshishouji');
}
Phone.name = 'zd' // 相当于类的静态成员
let nokia = new Phone()
console.log(nokia.name); // undefined
nokia.call()
// es6静态成员写法
class Phone{
// 静态成员
static name = 'as'
static ff(){
console.log('5adss');
}
}
let nokia = new Phone
console.log(nokia.name); // undefined
nokia.ff()// 未定义
3.继承与方法重写
// es5中的继承
function Phone(name, price) {
this.name = name
this.price = price
}
function SmartPhone(name, price ,color, size){
Phone.call(this, name, price)
this.color = color
this.size = size
}
Phone.prototype.dial = function(){
console.log('我可以打电话');
}
// 设置子集构造函数的原型
SmartPhone.prototype = new Phone
SmartPhone.prototype.constructor = SmartPhone
SmartPhone.prototype.phote = function(){
console.log('我可以拍照');
}
let chuizi = new SmartPhone('chuizi', 2555, '黑色', '5.5')
console.log(chuizi);
// es6 中的继承
class Phone{
constructor(name, price){
this.name = name
this.price = price
}
dial(){
console.log('我可以打电话')
}
}
class SmartPhone extends Phone{
constructor(name, price ,color, size){
super(name, price)
this.color = color
this.size = size
}
photo(){
console.log('我可以拍照');
}
// 方法重写,但是不可以调用父类中的方法
dial(){
super() // 会报错
console.log('我可以视频通话');
}
}
let xio = new SmartPhone('chuizi', 2555, '黑色', '5.5')
console.log(xio);
4.class的set()和get()
get name1(){
console.log('get调用了');
return this.name}
set name1(val){
console.log('get调用了');
return this.name}
1.17 ES6的数值扩展
// Number.EPSILON
function equal(a, b){
if(Math.abs(a - b) < Number.EPSILON){return true}else{return false}
}
console.log(0.1 + 0.2 === 0.3);
console.log(equal(0.1 + 0.2, 0.3));
// 二进制、八进制、十进制、十六进制
let b = 0b1010 // 10
let o = 0o777 // 511
let d = 100 // 100
let x = 0xff // 255
// Number.isFinite() 判断一个数是否是有限的
console.log(Number.isFinite(NaN)); // false
console.log(Number.isFinite(Infinity)); // false
// Number.isNaN() 判断一个数是否为NaN
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(Infinity)); // false
console.log('----------------');
// Number.parseInt(),Number.parseFloat() 字符串转换为整数,浮点数
console.log(Number.parseFloat('0.355as')); // 0.355
console.log(Number.parseInt('355as'));// 355
// Number.isInteger() 判断一个数是否为整数
console.log(Number.isInteger(2.5));// false
// Math.trunc() 将数字的小数部分抹掉
console.log(Math.trunc(3.6));// 3
// Math.sign() 判断一个数到底是正数负数还是0
console.log(Math.sign(100));// 1
console.log(Math.sign(-100));// -1
console.log(Math.sign(0));// 0
1.18 对象方法扩展
// Object.is() 判断两个值是否相等,和===相似,但有区别
console.log(Object.is(NaN, NaN)); //true
console.log(NaN === NaN);//false
// Object.assign() 将两个对象合并,前者的属性会被后者所覆盖,新的对象会包括两者的所有属性
let a = {
name: '阿萨德',
age: 15,
text: 111
}
let b = {
name: '阿萨德前端',
age: 56,
test: 22828
}
// console.log(Object.assign(a, b));
// Object.setPrototypeOf(),Object.getPrototypeOf() 设置和得到一个对象的原型对象,可以但不推荐这样去做
Object.setPrototypeOf(a, b) // 设置a的原型对象为b
console.log(a);
1.19 es6 模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的好处
- 防止命名冲突
- 代码复用
- 高维护性
模块化规范产品
ES6 之前的模块化规范有:
- CommonJS => NodeJS、Browserify
- AMD => requireJS
- CMD => seaJS
// export部分
// 分别暴露
export let a = '萨那点钱'
export function oo(){
console.log('我是模块化');
}
// import部分
<script type="module">
import * as m1 from './26es6模块化.js'
console.log(m1.a);
</script>
// 统一暴露
// export部分
let a = '萨那点钱'
function oo(){
console.log('我是模块化');
}
export {a, oo}
// import部分
<script type="module">
import * as m1 from './26es6模块化.js'
console.log(m1.a);
</script>
// 默认暴露
// export部分
export default {
name: 'asad',
inje(){
console.log('lkjdsh');
}
}
// import部分
<script type="module">
import * as m1 from './26es6模块化.js'
console.log(m1.default.name); // 需要加一层default
m1.default.inje()
</script>
模块导入方法汇总
// 模块导入方法汇总
// 通用的引入方式
import * as m1 from './26es6模块化.js'
console.log(m1.default.name);
m1.default.inje()
// 解构赋值的形式
import {default as m1} from './26es6模块化.js'
import {a, oo} from './26es6模块化.js'
import {a as pp, oo} from './26es6模块化.js'
// 简便形式,只适用于默认暴露
import m1 from './26es6模块化.js'
模块化使用的另外一种方式
// 在app.js中
import * as m1 from './26es6模块化.js'
console.log(m1.a);
// 在index.html中
<script src="./27app.js" type="module"></script>
babel对es6语法进行转化
1. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
2. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
3. 打包 npx browserify dist/js/app.js -o dist/bundle.js
2 es7新特性
// Array.prototype.incudes()方法,有返回true,没有返回false
let arr = [1, 6, 8, 6]
console.log(arr.includes(8));
// ** 运算符,和Math.pow()的作用相似
console.log(2 ** 5);
3 es8新特性
3.1 async函数和await表达式
// async函数返回的结果都是promise对象,其结果由return值决定
async function fn(){
// 这里返回的结果,和then()方法结果一样,如果是非promise对象,如字符串,数组等等,返回的promise对象状态为fulfilled,值为return 的值
// return '安徽'
// 抛出错误返回结果是fulfilled,值是return的值
// return new Error('kkk')
// 如果返回结果是promise对象,则由这个promise对象决定函数执行结果
return new Promise((resolve, reject)=>{
reject(111)
})
}
let temp = fn()
console.log(temp);
// await表达式
let p = new Promise((resolve,reject)=>{
resolve('用户数据')
})
async function fn(){
try{
let result = await p; // 通常在await后面放一个promise表达式,其返回结果就是promise成功的值
console.log(result);
}catch(e){
console.log(e);
}
}
fn()
await表达式
- await 必须写在 async 函数中
- await 右侧的表达式一般为 promise 对象
- await 返回的是 promise 成功的值
- await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理
读取文件案例(结合起来使得代码非常像同步编程)
const fs = require('fs')
function read1(){
return new Promise((resolve, reject)=>{
fs.readFile('../ES6/ES6_Promise/resources/为学.md',(err,res)=>{
if(err) return reject(err)
resolve(res)
})
})
}
function read2(){
return new Promise((resolve, reject)=>{
fs.readFile('../ES6/ES6_Promise/resources/插秧诗.md',(err,res)=>{
if(err) return reject(err)
resolve(res)
})
})
}
function read3(){
return new Promise((resolve, reject)=>{
fs.readFile('../ES6/ES6_Promise/resources/观书有感.md',(err,res)=>{
if(err) return reject(err)
resolve(res)
})
})
}
async function main(){
let read11 = await read1()
let read12 = await read2()
let read13 = await read3()
console.log(read11.toString());
console.log(read12.toString());
console.log(read13.toString());
}
main()
发送Ajax案例
function sendAJAX(url) {
return new Promise((resolve, reject) => {
const xml = new XMLHttpRequest()
xml.open('GET', url)
xml.send()
xml.onreadystatechange = function () {
if (xml.readyState === 4) {
if (xml.status >= 200 && xml.status < 300) {
resolve(xml.response)
}else(reject(xml.status))
}
}
})
}
// Promise.then()方法的测试
// sendAJAX('https://api.uomg.com/api/rand.qinghua').then((value)=>{
// console.log(value);
// },(reason)=>{
// console.log(reason);
// })
// async函数实现
async function main(){
let result = await sendAJAX('https://api.uomg.com/api/rand.qinghua')
console.log(result);
}
main()
3.2 对象方法扩展
-
Object.values()和 Object.entries()
- Object.values()方法返回一个给定对象的所有可枚举属性值的数组(对应还有一个Object.keys()方法获取所有的键名)
- Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
-
Object.getOwnPropertyDescriptors() 该方法返回指定对象所有自身属性的描述对象
let school = {
name: '尚硅谷',
citys: ['背', '上', '广'],
subject: ['咋混', '找我', '按时']
}
// Object.values()
console.log(Object.keys(school));
console.log(Object.values(school));
// Object.entries(),方便创建Map
console.log(Object.entries(school));
const m = new Map(Object.entries(school))
console.log(m.get('citys'));
// 对象所有自身属性的描述对象
console.log(Object.getOwnPropertyDescriptor(school));
// 返回结果见图
4 es9新特性
4.1 扩展运算符与rest参数
let school = {
name: '尚硅谷',
citys: ['背', '上', '广'],
subject: ['咋混', '找我', '按时']
}
let school2 = {
name: '黑马',
citys: ['背', '上', '广'],
like: '阿卡去'
}
function ff({name, ...rest}){
console.log(name);
console.log(rest);
}
ff(school)
let ooo = {...school, ...school2}
console.log(ooo); // {name: '黑马', citys: Array(3), subject: Array(3), like: '阿卡去'}
4.2 正则扩展
4.2.1 命名捕获分组
// ?<name>
let a = '<a href="https://www.baidu.com">尚硅谷</a>'
const reg = /<a href="(?<url>.*)">(?<text>.*)</a>/
let res = reg.exec(a)
console.log(res);
console.log(res.groups);
输出结果:
4.2.2 反向断言
let a = 'js546466阿萨德刚654489阿布'
// 正向断言
const reg = /\d+(?=阿布)/
let res = reg.exec(a)
// 反向断言
const reg2 = /(?<=德刚)\d+/
let res2 = reg2.exec(a)
console.log(res);
console.log(res2);
4.2.3 dotall模式
//dot . 元字符 除换行符以外的任意单个字符
let str = `
<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul>`;
// 没有dotall情况下
const reg = /<li>\s+<a>(.*?)</a>\s+<p>(.*?)</p>/
let res = reg.exec(str)
// 有dotall情况下
const reg2 = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/s
let res2 = reg2.exec(str)
console.log(res);
console.log(res2);
// 全局匹配
let data = []
const reg3 = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs
let res3;
while(res3= reg3.exec(str)){
data.push({title: res3[1], time: res[2]})
}
console.log(data);
5 es10新特性
5.1 Object.fromEntries()
// 二维数组 将二维数组转化为对象
const res = Object.fromEntries([['name','尚硅谷'],['aasd', '爱上规划']])
console.log(res);
// Map 将map转化为对象
const m = new Map()
m.set('name', '尚硅谷')
const res2 = Object.fromEntries(m)
console.log(res2);
// entries与fromEntries的作用正好相反,将对象转换成数组
const e = Object.entries({name:'尚硅谷'})
console.log(e);
5.2 Str.trimStart()方法和Str.trimEnd()方法分别去除字符串左边和右边的空白
// Str.trimStart()方法和Str.trimEnd()方法分别去除字符串左边和右边的空白
let str = ' asd '
console.log(str.trimStart());
console.log(str.trimEnd());
5.3 flat()方法和flatMap()方法
// flat将多维数组转化为低维数组,传递的参数为降低的维数,默认是1
let str = [2, 5, 6, 5, [6, 654, 58, [6, 4]]]
console.log(str.flat()); // [2, 5, 6, 5, 6, 654, 58, Array(2)]
console.log(str.flat(2)); // [2, 5, 6, 5, 6, 654, 58, 6, 4]
// flatMap()方法
const arr1 = [2, 5, 6, 5]
res = arr1.map((item)=>item * 10)
res1 = arr1.map((item)=>[item * 10])
res2 = arr1.flatMap((item)=>[item * 10])
console.log(res); //[20, 50, 60, 50]
console.log(res1); // [Array(1), Array(1), Array(1), Array(1)]
console.log(res2); // [20, 50, 60, 50]
5.4 Symbol.prototype.destription属性
let s = Symbol('山硅阿萨德')
console.log(s.description); // 山硅阿萨德
6 es11新特性
6.1 私有属性
class Person{
name
// 私有属性以#开头, 外部无法直接获取
#age
constructor(name, age){
this.name = name
this.#age = age
}
intro(){
console.log(this.name);
console.log(this.#age);
}
}
let i = new Person('安徽省级', 18)
console.log(i.#age); // 报错
i.intro()
6.2 Promise的allSettled()方法
const p1 = new Promise((resolve, reject)=>{
reject('商品属性-1')
})
const p2 = new Promise((resolve, reject)=>{
reject('商品属性-2')
})
// 两个方法传入的参数都为数组
// all方法的返回结果,当两个promise对象的结果都为true时为true,否则为false,返回的结果是异步任务失败的值
// allSettled()方法返回的结果无论如何都为true,返回的结果是异步任务的结果
// 用于执行批量异步任务
const res1 = Promise.all([p1,p2])
const res2 = Promise.allSettled([p1,p2])
console.log(res1);
console.log(res2);
6.3 String.prototype.matchAll()方法
let str = `
<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul>`;
const reg2 = /<li>.*?<a>(.*?)</a>.*?<p>(.*?)</p>/gs
// matchAll()方法匹配结果是一个可迭代数组
const res = str.matchAll(reg2)
for (v of res){
console.log(v);
}
console.log([...res]);
6.4 可选链操作符(?.)
function fn(config){
// 没有可选链操作符,需要一级一级判断,否则若没有传参,会报错
// const dbhost = config && config.db && config.db.host
// 有可选链操作符
const dbhost = config?.db?.host
console.log(dbhost);
}
fn({
db: {
host: '165246.596.56',
wd: 56464
},
fva: {
host: '165.596.56',
wd: '56q8w4'
}
})
6.5 动态import语句
const ff = document.querySelector('.btn')
ff.onclick = function(){
// 动态引入返回结果是一个promise对象
import('./46hello.js').then((modules)=>{
modules.hello()
})
}
6.6 BigInt类型
// 大整型 只要在整数后面加个n
let n = 524n
console.log(n, typeof(n)); // 524n 'bigint'
// 函数
let m = BigInt(521)
let k = BigInt(5.21)
console.log(m); // 521n
console.log(k); 报错
let max = Number.MAX_SAFE_INTEGER
console.log(max); // 9007199254740991
console.log(max + 1);// 9007199254740992
console.log(max + 2);// 9007199254740992
console.log(BigInt(max));// 9007199254740991n
console.log(BigInt(max) + BigInt(1));// 9007199254740992n
console.log(BigInt(max) + BigInt(2));// 9007199254740993n
6.7 globalThis绝对全局对象
console.log(globalThis); // 指向window对象
// nodejs环境下,指向global对象
\