ES6--阮一峰版笔记

发布时间:2024-11-24 11:01

一. ES6变量声明方法

ES6共有六种变量声明方法:var、function、const、let、import、class
顶层对象属性:在浏览器中,顶层对象指window,在node中,顶层对象指global,用var、function命令声明的顶层的全局变量,依旧是顶层对象的属性(原ES5中,顶层对象的属性赋值与全局变量赋值为同一件事),用let 、const、class命令声明的全局变量,不属于顶层对象的属性
ES6新增globalThis顶层对象,在任何环境下都是存在的,globalThis指向全局环境下的this.

二. Symbol

  1. symbol:原始数据类型,表明独一无二的值。
  • Symbol值使用Symbol()函数生成,typeOf symbol值 输出为"symbol"。
  • Symbol()函数不能有用new 命令,因为Symbol是一个原始类型的值,不是对象。
  • Symbol值不能与其他类型值进行运算,会报错;但是Symbol值可以显示转为字符串,可以转为布尔值(true), 但不能转换为数值
  • Symbol可以设置参数对Symbol值进行描述
  1. Symbol.prototype.description:在Symbol函数创建Symbol值时,用参数添加一个描述。读取这个描述需要将 Symbol 显式转为字符串比较麻烦,后面ES2019提供了一个 Symbol 值的实例属性description,直接返回 Symbol 值的描述。
const sym = Symbol('foo');
sym.description // "foo"
  1. 作为属性名的 Symbol,不能用点运算符;在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中;Symbol 值作为属性名时,该属性还是公开属性
  2. Object.getOwnPropertySymbols(): Symbol 值作为属性名,遍历对象的时候,该属性不会出现在for…in、for…of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()。 Object.getOwnPropertySymbols()可以获取指定对象的所有 Symbol 属性名,该方法返回当前对象的所有座用作属性名的Symbol值的数组。:,Reflect.ownKeys()方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
  3. Symbol.for(),Symbol.keyFor() :
  • Symbol.for()接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。与Symbol()不一样的是,Symbol()不会被登记()在全局中进行搜索。
  • Symbol.keyFor() :返回一个已登记的 Symbol 类型值的key
  1. 内置的 Symbol 值
  • Symbol.hasInstance: 对象的Symbol.hasInstance属性,指向一个内部方法。当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
  • Symbol.isConcatSpreadable:对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。该属性默认为undefined,与设置为true时的结果一直,表示默认展开。而类似数组的则正好相反,默认不展开。
  • Symbol.species:指向一个构造函数。创建衍生对象时,会使用该属性
  • Symbol.match:对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。
  • Symbol.replace:对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。
  • Symbol.search:对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。
  • Symbol.split:对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值
  • Symbol.iterator:对象的Symbol.iterator属性,指向该对象的默认遍历器方法
  • Symbol.toPrimitive:对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值
  • Symbol.toStringTag:对象的Symbol.toStringTag属性,指向一个方法
  • Symbol.unscopables:对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。

三. 箭头函数

特点

  1. 箭头函数没有自己的this对象
  2. 箭头函数的this指向在定义的时候外层第一个普通函数的this(一旦确定就不再改变,除非外外层第一个普通函数的this指向改变);普通函数的this指向在执行的时候的对象
    :call()、apply()、bind()也不能改变其指向
  3. 被继承的外层普通函数的this指向改变,箭头函数的this指向会跟着改变
  4. 箭头函数外层没有普通函数,严格模式和非严格模式下它的this都会指向window(全局对象)
    普通函数在严格模式下,指向undefined,非严格模式下指向全局对象
  5. 箭头函数的this指向全局对象,会报arguments未声明的错误;箭头函数的this指向普通函数this时,其arguments继承于该普通函数
  6. 箭头函数不能用new 来调用,因为其没有constructor,因此不支持new target属性
  7. 箭头函数不支持重名函数参数,普通函数的函数参数支持重名

不适用情景

  1. 定义对象方法时,在对象方法中不能用箭头函数,因为对象不单独构成作用域
  2. 需要动态的this时候,如回调函数的this

注意事项

  1. 箭头函数一条语句返回对象字面量,需要加括号
  2. 箭头函数在参数和箭头之间不能换行
  3. 箭头函数的解析顺序相对||靠前

四. Promise

  1. Promise 的含义及其三种状态
  • 意义:异步编程解决方案。语法上来讲是一个对象,获取异步操作的消息。可将异步操作以同步操作的流程表达出来,避免层层嵌套
  • 三种状态:pending 、fullfilled、rejected
  • 2个特点:对象状态不受外界影响,只有异步操作的结果可以决定该对象处于哪一种状态;一旦状态改变,就不会改变
  • 3个缺点:无法取消promise,一旦新建,立即执行,无法中断;promise内部抛出的错误需要设置回调函数才能反映到外部;处于pending状态时,无法得到promise处于哪一个阶段
  1. 基本用法
    创建promise实例,Promise构造函数接收一个函数作为参数,该函数有两个参数,分别为resolve,reject
const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
  • resolve:将promise状态从未完成变为成功,在异步操作成功时调用,并将异步操作结果作为参数传出去,避免回调地狱
  • reject:将promise状态从未完成变为失败,在异步操作失败时调用,并将错误作为参数传递出去
//Promise异步加载图片
function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    const image = new Image();

    image.onload = function() {
      resolve(image);
    };

    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    image.src = url;
  });
}
  1. Promise.prototype.then()
  • 该方法接收两个参数回调函数作为参数,第一个回调函数在Promise对象状态变为resloved时调用,第二个回调函数在Promise对象变为rejected时调用,二者接收Promise对象传出的值作为参数。
  • 该方法返回的是一个新的promise实例,可用于链式编程,上一个promise实例对象得返回值为下一个then的参数
  1. Promise.prototype.catch(),为then.(null,rejection)或then.(undefined,rejection)的别名,作用与promise.then( )一致,只是参数个数不一样用于指定发生错误时的回调函数;该方法返回的是一个promise对象,后续可继续调用.then()方法;该方法中可再次抛出错误
// 写法一(注意try{}catch(){}的用法)
const promise = new Promise(function(resolve, reject) {
  try {
    throw new Error('test');
  } catch(e) {
    reject(e);
  }
});
promise.catch(function(error) {
  console.log(error);
});

// 写法二
const promise = new Promise(function(resolve, reject) {
  reject(new Error('test'));
});
promise.catch(function(error) {
  console.log(error);
});

(1)可捕获的错误有:Promise对象状态变为rejected时抛出的错误;.then()方法抛出的错误
(2)Promise错误特性:

  • 若promise状态变为resolved,则错误无法被捕获
  • Promise对象错误具有冒泡性质,会一直向后传递,直至被捕获
  • Promise错误若无catch()指定处理错误的回调函数,则不会将错误传递出去,不影响promise外的代码,外层代码没有反应
  • try{ } catch{ } 两个成对出现,前一个允许定义在执行时进行错误测试的代码块?,
  • catch用于在try代码块发生错误时进行捕获
  • finally{ }不论前面的 try{}与catch{}是否产生异常都会执行代码
  • throw { }用于抛出(创建)错误,可放在try{}内部,自定义错误
  1. Promise.prototype.finally():指定不管promise对象最后状态如何,都会执行的操作
  • 该方法不接受任何参数,表明finally方法的回调函数与前面promise的状态无关,其本质为then方法的特例
  • 总会返回原来的值
  1. Promise.all(), 将多个promise实例a,b,c….(若abc…不是实例,则首先调用resolve()方法)包装成一个新的Promise实例p,其参数可以不是数组,但必须具有iterator接口。
const p = Promise.all([p1, p2, p3]);
  • 实例a b c …的状态都变成了fulfilled,p才会fulfilled,abc…的返回值组成一个数组传递给p的回调函数
  • 实例 a b c…中有一个状态为rejected,p 都为rejected,第一个a的返回值会传递给p的回调函数
  • 实例a b c … 有自己的catch()方法,则一旦这些实例的状态为rejected,则仅触发自己的catch,而不会触发promise.all()的catch(),因为等所有的catch()方法调用后,实例的状态已经变成了resolved,promise.all()的catch()方法无法捕获错误
  1. **Promise.race()**方法将多个promise实例abc…包装成一个新的Promise实例p,各个子实例中,谁先改变状态,p的状态会跟着改变,并且将先改变状态的实例的返回值传递给p
  2. **Promise.allSettled()**方法(ES2020引进)接收一个数组作为参数,数组每个成员都为一个Promise对象
  • 该方法返回一个新的Promise对象,只有数组内所有成员的状态变更(不论是fulfilled还是rejected),返回的新的Promise对象的状态才会发生变更,且变更的状态皆为fulfilled
  • 其.then()方法中的回调函数会接收一个数组作为参数,该数组的每个成员对应前面数组的每个promise对象
  1. **Promise.any()**方法将多个promise实例abc…包装成一个新的Promise实例P
  • 实例a b c …的状态都变成了rejected,p才会rejected
  • 只要有一个为fulfilled,则p的状态为fulfilled,abc…的返回值组成一个数组传递给p的回调函数
  • Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。
  1. Promise.resolve(),将现有对象转为Promise对象
    该方法参数分类
  • Promise实例:原封不动返回该promise对象实例
  • thenable 对象 :指具有then方法的对象,将该对象转为Promise对象,然后立即执行thenable方法的.then()方法
  • 不是thenable对象,或者根本不是对象:返回一个状态为resolved的promise对象
  • 不带任何参数:直接返回一个状态为resolved的promise对象
    注:立即resolve()的Promise对象,是在本轮“事件循环event loop ”的结束时执行,而非在下一轮事件循环开始时执行。
  1. **Promise.reject()**返回一个promise实例,状态为rejected
  • Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。
  1. Promise对象的应用
  • 图片加载、发送异步请求 手写代码
  • 与Generator函数相结合
  • 不论函数是异步或者同步,使用then()方法指定下一流程,用catch()处理抛出的错误
Promise.resolve().then(f)
  1. 手写promise
//创建一个Promise的类
  class Promise{
    constructor(executer){//构造函数constructor里面是个执行器
      this.status = 'pending';//默认的状态 pending
      this.value = undefined//成功的值默认undefined
      this.reason = undefined//失败的值默认undefined
      //状态只有在pending时候才能改变
      let resolveFn = value =>{
        //判断只有等待时才能resolve成功
        if(this.status == pending){
          this.status = 'resolve';
          this.value = value;
        }
      }
      //判断只有等待时才能reject失败
      let rejectFn = reason =>{
        if(this.status == pending){
          this.status = 'reject';
          this.reason = reason;
        }
      }    
      try{
        //把resolve和reject两个函数传给执行器executer
        executer(resolve,reject);
      }catch(e){
        reject(e);//失败的话进catch
      }
    }
    then(onFufilled,onReject){
      //如果状态成功调用onFufilled
      if(this.status = 'resolve'){
        onFufilled(this.value);
      }
      //如果状态失败调用onReject
      if(this.status = 'reject'){
        onReject(this.reason);
      }
    }
  }

Set

新的数据结构,类似于数组,但成员的值都是唯一的,实现iterator接口,所以可使用扩展运算符与for…of…进行遍历
Set构造函数可用任一具有iterator接口的数据作为参数生成Set结构
特点
1.向Set中加入值时,不会发生类型转换,内部判断方法类似于 严格相等===,
但是=== 与==中,NaN不等于自身,Set中等于自身
2.Array.from()将Set结构转为数组,可用于数组去重
set的属性与方法:
1.size 返回集合元素与个数
2. add 增加新元素并返回新集合
3. delete 删除元素,返回布尔值
4. has 检测集合中是否包含某个元素,返回布尔值
5. clear 清空集合,返回undefined
6. 四个遍历方法:
(1) Set.prototype.keys():返回键名的遍历器 注:Set的键名与键值相同
(2)Set.prototype.values():返回键值的遍历器
(3)Set.prototype.entries():返回键值对的遍历器
(4)Set.prototype.forEach():使用回调函数遍历每个成员

 //声明一个 set
        let s = new Set();
        let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿']);

        //元素个数
        // console.log(s2.size);
        //添加新的元素
        // s2.add('喜事儿');
        //删除元素
        // s2.delete('坏事儿');
        //检测
        // console.log(s2.has('糟心事'));
        //清空
        // s2.clear();
        // console.log(s2);

        for(let v of s2){
            console.log(v);
        }

集合操作:

   let arr1 = [1,2,3,4,5,4,3,2,1];
        //1. 数组去重
        let result1 = [...new Set(arr)];
        console.log(result1);

        //2. 交集
        let arr2 = [4,5,6,5,6];
        let result2 = [...new Set(arr1)].filter(item => {
            let s2 = new Set(arr2);// 4 5 6
             if(s2.has(item)){
                 return true;
             }else{
                 return false;
             }
        });
        //简化写法 
         let result22 = [...new Set(arr1)].filter(item => new Set(arr2).has(item));
         console.log(result);

        //3. 并集
         let union = [...new Set([...arr, ...arr2])];
         console.log(union);

        //4. 差集
        let diff = [...new Set(arr1)].filter(item => !(new Set(arr2).has(item)));
        console.log(diff);

weakSet

与Set类似,也是不重复的值的集合,
与Set不同的点:该数据结构成员只能是对象,而不能是其他类型的值;该数据结构中的对象为弱引用,即垃圾回收机制不考虑weakSet对该对象的引用,该结构只适用于存放临时对象及其信息,不适合被引用,该结构不可被遍历
三个方法
WeakSet.prototype.add(value):向 WeakSet 实例添加一个新成员。
WeakSet.prototype.delete(value):清除 WeakSet 实例的指定成员。
WeakSet.prototype.has(value):返回一个布尔值,表示某个值是否在WeakSet实例中
WeakSet 没有size属性,没有办法遍历它的成员。

Map

它类似于对象,也是键值对的集合。但是“键”范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用扩展运算符和for…of…进行遍历。对同一个键进行多次赋值,后面的值将覆盖前面的值。Map的键读取的是该值的内存地址,只要两个值严格相等,则将其视为同一个键。(NaN例外,虽然NaN与自身不严格相等,但Map会当成同一个键)
Map 的属性和方法:
1.size() 返回集合Map个数

  1. set ()增加新元素并返回当前map,可用链式写法
  2. get ()返回键名对象的键值
  3. has() 检测map中是否包含某个元素,返回布尔值
  4. clear() 清空集合,返回undefined
  5. delete()清空某个元素,返回布尔值
  6. map.forEach,实现遍历
 //声明 Map
        let m = new Map();

        //添加元素
        m.set('name','尚硅谷');
        m.set('change', function(){
            console.log("我们可以改变你!!");
        });
        let key = {
            school : 'ATGUIGU'
        };
        m.set(key, ['北京','上海','深圳']);

        //size
        console.log(m.size);

        //删除
         m.delete('name');

        //获取
         console.log(m.get('change'));
         console.log(m.get(key));

        //清空
         m.clear();

        //遍历
        for(let v of m){
            console.log(v);
        }
		
		/*与其他数据结构相互转换*/
		//转换为数组 ...扩展运算符
		const myMap = new Map()
 		.set(true, 7)
  		.set({foo: 3}, ['abc']);
		[...myMap]
		
		//数组转为Map
		new Map([
 		[true, 7],
  		[{foo: 3}, ['abc']]
		])
		
		//Map转为对象
		function strMapToObj(strMap) {
  			let obj = Object.create(null);
  			for (let [k,v] of strMap) {
    		obj[k] = v;
  		}
  			return obj;
		}
		const myMap = new Map()
  			.set('yes', true)
  			.set('no', false);
		strMapToObj(myMap)

		//对象转为Map Object.entries()或者自己构造转换函数
		let obj = {"a":1, "b":2};
		let map = new Map(Object.entries(obj))
		
		//Map转为JSON
		//(1)Map 的键名都是字符串,这时可以选择转为对象 JSON。
		function strMapToJson(strMap) {
  			return JSON.stringify(strMapToObj(strMap));
		}
		let myMap = new Map().set('yes', true).set('no', false);
		strMapToJson(myMap)
		//(2)Map 的键名有非字符串,这时可以选择转为数组 JSON
		function mapToArrayJson(map) {
  			return JSON.stringify([...map]);
		}
		let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
		mapToArrayJson(myMap)

WeakMap

与Map结构相似,用于生成键值对的集合
区别:
(1) WeakMap只接受对象作为键名(null除外),其键名所指向的对象,不计入垃圾回收机制,与WeakSet类似,WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。
(2) 没有遍历操作(即没有keys()、values()和entries()方法),也没有size属性。不支持clear()
属性与方法:get()、set()、has()、delete()。
用途: DOM 节点作为键名;部署私有属性

WeakRef

WeakRef() 构造函数直接创建对象的弱引用(创建对象)
WeakRef实例对象有方法:deref()
作用:作为缓存,未被清除时可以从缓存取值,一旦清除缓存就自动失效。

Iterator与for…of循环

Iterator

  1. Iterator作用:为各种数据结构,提供统一的访问接口;使数据结构成员按某种顺序排列;for…of循环
  2. iterator的next方法:调用一次,返回value与done,前者是当前成员的值,done是一个布尔值,表示遍历是否结束
  • 模拟遍历器next方法
var it = makeIterator(['a', 'b']);

it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true }

function makeIterator(array) {
  var nextIndex = 0;
  return {
    next: function() {
      return nextIndex < array.length ?
        {value: array[nextIndex++], done: false} :
        {value: undefined, done: true};
    }
  };
}
  1. symbol.iterator:数据结构的一个属性,执行该属性会返回一个遍历器对象,即为数据结构部署接口
  2. 原生具备遍历器接口的:Array、Map、Set、String、TypedArray、arguments对象、NodeList对象。其余数据结构的iterator接口需要手动部署
  3. 使用场合:
  • 解构赋值
  • 扩展运算符
  • yiled
  • 数组的遍历
  1. return()、throw()方法

for…of循环

  1. for…in… 获得键名
  2. for…of…获得键名
  3. entries()返回键名-键值对对象
  4. keys()返回键值对象
  5. forEach

Generator

  1. 基本概念:一种异步编程解决方案,Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数,返回的遍历器对象,可以依次遍历Generator 函数内部的每一个状态
  • function关键字与函数名之间有一个星号*
  • 函数体内部使用yield表达式,定义不同的内部状态,yiled表达式是暂停执行的标志;当调用遍历器对象的next()方法时,遇到yiled表达式就暂停后续操作,并将该yiled后面的表达式的值,作为返回的对象的value属性值
  • yiled与return的联系都能返回紧跟在语句后面的那个表达式的值,区别在于遇到yiled暂停执行,下一次继续从该位置执行。而return不具备位置记忆功能,一个return 只能执行一次,yiled可以执行多次
  • yile表达式只能用在generator函数里面,其余地方会报错
  1. generator 与 iterator的联系
  • 对象的Symbol.iterator方法为遍历器生成函数,generator也是遍历器生成函数,因此将Generator 赋值给对象的Symbol.iterator属性,从而使得该对象具有 Iterator 接口
  • generator函数执行后,会返回一个遍历器对象,改遍历器对象本身的symbol.iterator属性也是遍历器对象生成函数,执行后返回自身这个遍历器对象
  1. next方法参数:yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
  2. for…of 循环:for…of循环可以自动遍历 Generator 函数运行时生成的Iterator对象,且此时不再需要调用next方法。因此,可通过generator函数为原生对象添加接口。或将generator函数加到对象的symbol.iterator属性上,使得对象可以遍历
  3. Generator.prototype.throw()方法:Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获
  4. Generator.prototype.return()方法:Generator 函数返回的遍历器对象,有return()方法,可以返回给定的值,并且终结遍历 Generator 函数
  5. yield* 表达式 : Generator 函数内部,调用另一个 Generator 函数。需要在前者的函数体内部,自己手动完成遍历,而ES6提供的yield*表达式可以实现在一个generator函数里自动调用另一个generator函数
  • yield命令可以进行数组打平 手写代码
function* iterTree(tree) {
  if (Array.isArray(tree)) {
    for(let i=0; i < tree.length; i++) {
      yield* iterTree(tree[i]);
    }
  } else {
    yield tree;
  }
}

const tree = [ 'a', ['b', 'c'], ['d', 'e'] ];
  1. Generator函数的this: 函数总是返回一个遍历器,这个遍历器是生成器函数的实例,同样继承生成器函数的prototype上的方法。
  • 不能将生成器函数当成普通的构造函数,如果将其当成普通的构造函数,其返回的遍历器对象不能获取其内部的this对象(个人理解为,生成器函数与构造函数的概念互斥)
  • 不能使用new 命令来调用生成器函数

Async与Await

async本质为Generaor函数的语法糖:async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已

  1. async 对 Generator函数的改进:
  • 内置执行器:Generator 函数的执行必须靠执行器,即必须调用next方法,而async函数有内置的执行器,与普通函数调用一致
  • 语义更清晰:async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
  • 更广的适用性:yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(虽然是原始类型的值,但会立马被转换为resolved的promise对象)
  • 返回值:async函数的返回值是 Promise 对象,Generator 函数的返回值是 Iterator 对象,返回的Promise对象比Iterator对象方便很多,可使用.then方法指定下一步的操作
  1. async语法
  • async函数返回一个promise对象:该函数async内部return语句返回的值,会成为then方法回调函数的参数;函数内部抛出的错误也会导致返回的promise对象变为rejected状态,抛出的错误会被catch方法回调函数接收到
  • promise对象状态变化:内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误
  1. await命令:一般情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值;特殊情况下,await命令后面是一个thenable对象(即定义了then方法的对象),那么await会将其等同于 Promise 对象
  • 错误处理:若await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject;想要防止错误影响后续的函数调用,则将await命令放在try{ }catch(e){ }中
    注意:await后面的promise对象状态若为rejected,会影响后续函数调用,可放在try{ }模块中;多个await后面的异步操作,若不存在继发关系,最好使其同时触发;await只能用在async函数中
  1. async函数的实现原理:Generator 函数和自动执行器,包装在一个函数里。
  2. 顶层await:早期的语法规定,await函数只能出现在async函数内部

FinalizationRegistry

清理注册表功能

Proxy

用于修改某些操作默认行为,属于元编程
Proxy(target,handler)构造函数,用来生Proxy实例,target为拦截目标对象,handler为定制拦截行为的对象(操作)

  1. handler 若没设置任何拦截,则proxy实例就等于被代理的对象
  2. 将proxy设置为对象的属性,则可以通过调用对象属性使用
    将proxy作为另一对象的原型对象,也会调用
  3. Proxy支持的常见拦截操作:
    (1)get(target, propKey, receiver):拦截对象属性的读取,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选,最后一个参数总是指向原始的读操作所在的那个对象,一般情况下就是 Proxy 实例。
    :如果一个属性不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性,否则通过 Proxy 对象访问该属性会报错。
    (2)set(target, propKey, value, receiver):拦截对象属性的赋值操作,四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。
    :如果一个属性不可写(writable),则 set方法不起作用;set代理应当返回一个布尔值。严格模式下,set代理如果没有返回true,就会报错。
    (3)has(target, propKey):拦截propKey in proxy的操作(拦截的是HasProperty操作),两个参数,目标对象、需查询的属性名
    :若某属性不可配置或目标对象不可扩展,则不得使用has方法进行拦截,会报错;该拦截只对in运算符生效,对for…in循环不生效
    (4)ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、 Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
    (5)getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象或undefined
    (6)getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),拦截获取对象原型
    (7) setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值
    (8) apply(target,contex,args):拦截函数的调用、call、apply,三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组。
    (9) construct(target,args,new Target) 方法用于拦截new命令,
    三个参数,目标对象(需是函数),构造函数的参数数组,用new创建实例对象时new命令作用的构造函数。
    该方法返回的必须是对象,否则报错;拦截的目标对象是函数;
const handler = {
  construct (target, args, newTarget) {
    return new target(...args);
  }
};

(10) deleteProperty() ,拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除
(11) defineProperty(),拦截了Object.defineProperty()操作。
:,如果目标对象不可扩展(non-extensible),则defineProperty()不能增加目标对象上不存在的属性,否则会报错。另外,如果目标对象的某个属性不可写(writable)或不可配置(configurable),则defineProperty()方法不得改变这两个设置。
(12)**preventExtensions()**拦截Object.preventExtensions()。该方法必须返回一个布尔值,否则会被自动转为布尔值。只有目标对象不可扩展时(即Object.isExtensible(proxy)为false proxy.preventExtensions 才能返回true,否则会报错。
(13)this的指向,proxy代理的情况下,this指向proxy代理。
应用:代理服务器

Reflect

将Object对象的一些明显属于语言内部的方法,放在Reflect对象上;修改某些Object方法的返回结果,让其变得更合理; 让Object操作都变成函数行为;Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法
(1)静态方法:13个静态方法,与Proxy一一对应
Reflect.apply(target, thisArg, args)
Reflect.construct(target, args)
Reflect.get(target, name, receiver)
Reflect.set(target, name, value, receiver)

a. 若name属性设置了赋值set、读取get函数,则赋值/读取函数的this指向receiver
b.如果 Proxy对象和 Reflect对象联合使用,前者拦截赋值操作,后者完成赋值的默认行为,而且传入了receiver,那么Reflect.set会触发Proxy.defineProperty拦截。
Reflect.defineProperty(target, name, desc)
Reflect.deleteProperty(target, name)
Reflect.has(target, name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)
(2)应用:使用 Proxy 实现观察者模式

const queuedObservers = new Set();

const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});

function set(target, key, value, receiver) {
  const result = Reflect.set(target, key, value, receiver);
  queuedObservers.forEach(observer => observer());
  return result;
}

Class

作为对象的模板,通过class关键字,可以定义类
class 实例:

 //class
        class Shouji{
            //构造方法 名字不能修改
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }

            //方法必须使用该语法, 不能使用 ES5 的对象完整形式
            call(){
                console.log("我可以打电话!!");
            }
        }

        let onePlus = new Shouji("1+", 1999);

        console.log(onePlus);

关键点:

  1. Object.assign(),一次向类添加多个方法
  2. 类内部定义的方法不可枚举
  3. constructor()是类的默认方法,创建实例时调用,默认返回类的实例
  4. 类必须使用new 关键字调用
  5. 与ES5相同,使用get、set关键字进行属性存取拦截
  6. 类的属性名,可以用表达式
  7. 严格模式
  8. 类不存在变量提升
  9. static:类的静态static成员的属性或者方法不能被实例对象访问(类似于函数对象的属性与方法不能被实例对象访问)注:静态方法中的this指向类,而非实例;ES2022中引入了静态块(static块)在类生成时运行对静态属性进行初始化
 class Phone{
            //静态属性
            static name = '手机';
            static change(){
                console.log("我可以改变世界");
            }
        }

        let nokia = new Phone();
        console.log(nokia.name);//输出为undefined
        console.log(Phone.name);//输出为手机
  1. 实例属性可以写在constructor()方法中,也可以写在类的最顶层
  2. 私有属性(方法):在类中定义时使用#关键字,将方法(属性)设置为私有,外部无法访问,只能在类内部访问;可以将私有属性设置为静态属性static #;子类可以继承私有属性,但通过Object.creat()或Object.setPrototype()不可以继承私有属性
    (1)try…catch结构可以用来判断是否存在某个私有属性。
class A {
  use(obj) {
    try {
      obj.#foo;
    } catch {
      // 私有属性 #foo 不存在
    }
  }
}
const a = new A();
a.use(a); // 报错

(2) in运算符也可以判断是否有私有属性(对于Object.Create()、Object.setPrototypeof()形成的继承是无效的,因为这两种继承无法传递私有属性)

class A {
  use(obj) {
    if (#foo in obj) {
      // 私有属性 #foo 存在
    } else {
      // 私有属性 #foo 不存在
    }
  }
}
  1. new.target属性:new命令引入了一个new.target属性,该属性一般用在构造函数之中,返回new命令作用于的那个构造函数;子类继承父类时,new.target返回子类
  2. 类的继承:
    (1)extends关键字继承父类方法与属性、super关键字(必须在constructor使用,先继承,后实例,只有调用super后,才可以使用this关键字)调用父类的方法与属性,constructor定义类的构造函数并初始化
    (2)子类的实例也是父类的实例
    (3)除私有属性外,父类所有方法与属性子类都继承(包括静态方法)
    (4)Object.getPrototypeOf()方法可以用来从子类上获取父类。
  3. super关键字,即可当做函数使用,也可当做对象使用(需显示指定为哪种类型)
    (1)做函数调用:代表父类的构造函数,子类的构造函数必须执行一次super函数,返回的是子类的实例;只能用于子类构造函数之中
    (2)做对象:在普通方法中,指向父类的原型对象;在静态方法中,指向父类
    普通方法中:子类普通方法中通过super调用父类的方法时,方法内部的this指向当前的子类实例;由于this指向子类实例,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性(普通——super父类原型对象——this指向子类实例)
    静态方法中:在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例(静态——super父类——this指向子类)
 class Phone{
            //构造方法
            constructor(brand, price){
                this.brand = brand;
                this.price = price;
            }
            //父类的成员属性
            call(){
                console.log("我可以打电话!!");
            }
        }

        class SmartPhone extends Phone {
            //构造方法
            constructor(brand, price, color, size){
                super(brand, price);// Phone.call(this, brand, price)
                this.color = color;
                this.size = size;
            }

            photo(){
                console.log("拍照");
            }

            playGame(){
                console.log("玩游戏");
            }

            call(){
                console.log('我可以进行视频通话');
            }
        }

        const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
        // console.log(xiaomi);
        xiaomi.call();
        xiaomi.photo();
        xiaomi.playGame();
  1. 特殊的get与set属性,可以在父类中设置这两个属性,子类可以直接调用
 // get 和 set  
        class Phone{
            get price(){
                console.log("价格属性被读取了");
                return 'iloveyou';
            }

            set price(newVal){
                console.log('价格属性被修改了');
            }
        }

        //实例化对象
        let s = new Phone();

        // console.log(s.price);
        s.price = 'free';
  1. 类的 prototype 属性和__proto__属性
    (1)子类.proto === 父类
    (2)子类.prototype.proto === 父类.prototype
class A {
}

class B extends A {
}

B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
  1. 实例的_proto_属性
    子类.__ proto __ . __ proto __ === 父类.proto
    子类.__ proto__.__proto__可以修改父类实例的行为
  2. 原生构造函数的继承
    原生构造函数通常用来生成数据结构,是无法继承的
    Boolean()
    Number()
    String()
    Array()
    Date()
    Function()
    RegExp()
    Error()
    Object()

数值扩展

Number.EPSILON 是 JavaScript 表示的最小精度
二进制(0b)与八进制(0o)
Number.isFinite( )检测数值是否为有限
Number.isNaN( )检测一个数值是否为NaN
Number.parseInt( )将字符串提取为整数
Number.parseFloat( )将字符串提取为浮点数
Number.isInteger( ) 判断一个数是否为整数
Math.sign 判断一个数到底为正数 负数 还是零
Math.trunc( ) 去除小数部分,返回整数部分

 //0. Number.EPSILON 是 JavaScript 表示的最小精度
        EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16
        // 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))

        //1. 二进制和八进制
         let b = 0b1010;
        // let o = 0o777;
        // let d = 100;
        // let x = 0xff;
        // console.log(x);

        //2. Number.isFinite  检测一个数值是否为有限数
         console.log(Number.isFinite(100));
        // console.log(Number.isFinite(100/0));
        // console.log(Number.isFinite(Infinity));
        
        //3. Number.isNaN 检测一个数值是否为 NaN 
         console.log(Number.isNaN(123)); 

        //4. Number.parseInt Number.parseFloat字符串转整数
         console.log(Number.parseInt('5211314love'));
        // console.log(Number.parseFloat('3.1415926神奇'));

        //5. Number.isInteger 判断一个数是否为整数
         console.log(Number.isInteger(5));
        // console.log(Number.isInteger(2.5));

        //6. Math.trunc 将数字的小数部分抹掉  
        console.log(Math.trunc(3.5));

        //7. Math.sign 判断一个数到底为正数 负数 还是零
        console.log(Math.sign(100));
        console.log(Math.sign(0));
        console.log(Math.sign(-20000));

对象方法扩展

1.Object.is(a, b) 判断a,b两个值是否完全相等, 与===不同之处可以比较NaN
2.Object.assign(obj1, obj2) 对象的合并(实际为obj2将obj1覆盖)
3. Object.setPrototypeOf (obj1,obj2)设置原型对象(将obj2设置为obj1的原型对象)

 //1. Object.is 判断两个值是否完全相等 
        console.log(Object.is(120, 120));//  
        console.log(Object.is(NaN, NaN));// 
        console.log(NaN === NaN);// 

        //2. Object.assign 对象的合并
         const config1 = {
             host: 'localhost',
             port: 3306,
             name: 'root',
             pass: 'root',
             test: 'test'
         };
         const config2 = {
             host: 'http://atguigu.com',
             port: 33060,
             name: 'atguigu.com',
             pass: 'iloveyou',
             test2: 'test2'
         }
        // console.log(Object.assign(config1, config2));

        //3. Object.setPrototypeOf 设置原型对象  Object.getPrototypeof
        const school = {
            name: '尚硅谷'
        }
        const cities = {
            xiaoqu: ['北京','上海','深圳']
        }
        Object.setPrototypeOf(school, cities);
        console.log(Object.getPrototypeOf(school));
        console.log(school);

模块化

优势:防止命名冲突;代码复用;高维护性
模块化语法:

  1. export 用于暴露模块
    分别暴露:在每个对象前面使用export暴露
    统一暴露:export{要暴露的模块,,,,}
    直接暴露:export default{ 要暴露的数据}
    对应的导入后调用时:模块名.defalut.方法(属性名)
  2. import用于导入模块:(在编译阶段就导入了)
    统一引入:import * as 文件名(去除扩展名) from “路径”
    解构赋值:import {对象(内容)1, 对象(内容)2,…} from “路径”
    import 命令具有提升效果
  3. export与import的复合写法
    表示在一个模块中,先输入后输出同一个模块,相当于对外转发了这个模块,导致当前模块不能直接使用引入输出的模块
  4. 模块的继承
//2. 解构赋值形式
         import {school, teach} from "./src/js/m1.js";
        // 当导入时有两个相同的内容名,使用别名
         import {school as guigu, findJob} from "./src/js/m2.js";
         //对于直接暴露的内容的引入,有相同的内容名,也使用别名
         import {default as m3} from "./src/js/m3.js";

直接引入(针对直接暴露):import 文件名(去除扩展名)from “路径”
模块引入的另一种方法
a.建立单独的js文件,将所有需要引入的模块在这个文件中引入
b.再在真正需要引入模块的文件里将1建立的js文件用src方法引入

//需要设置类型
<script src="./src/js/app.js" type="module"></script>

Babel的使用(主要是解决兼容性问题):
5. 安装工具 npm i babel-cli babel-preset-env browserify(webpack) -D
6. 编译 npx babel src/js -d dist/js --presets=babel-preset-env
7. 打包 npx browserify dist/js/app.js -o dist/bundle.js

ES7新特性

Array.prototype.includes用来检测数组中是否包含某个元素,返回布尔类型值

		 const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];

        //判断
         console.log(mingzhu.includes('西游记'));//输出true
         console.log(mingzhu.includes('金瓶梅'));

**为指数运算符 用来实现幂运算,与Math.pow功能一致

    // **
    console.log(2 ** 10);// 
    console.log(Math.pow(2, 10));

ES8新特性

1.async(与then类似)

async 函数的返回值为 promise 对象
若返回结果不是promise: 该函数的返回值除了主动抛出错误(此时为rejected),其余情况下返回值都是resolved Promise对象,即此时返回的promise对象无论如何都成功
若返回结果为promise: 则返回值promise对象的成功与否取决于返回结果promise的成功

2.await

await 必须写在 async 函数中
await 右侧的表达式一般为 promise 对象
await 返回的是 promise 成功的值
await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
.async 与await相结合可以使异步类似于同步???(没理解)
案例:async与await结合进行读取数据

//1. 引入 fs 模块
const fs = require("fs");

//读取『为学』
function readWeiXue() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/为学.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readChaYangShi() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/插秧诗.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

function readGuanShu() {
    return new Promise((resolve, reject) => {
        fs.readFile("./resources/观书有感.md", (err, data) => {
            //如果失败
            if (err) reject(err);
            //如果成功
            resolve(data);
        })
    })
}

//声明一个 async 函数
async function main(){
    //获取为学内容
    let weixue = await readWeiXue();
    //获取插秧诗内容
    let chayang = await readChaYangShi();
    // 获取观书有感
    let guanshu = await readGuanShu();

    console.log(weixue.toString());
    console.log(chayang.toString());
    console.log(guanshu.toString());
}

main();

案例2:async与awit结合进行封装ajax请求

 // 发送 AJAX 请求, 返回的结果是 Promise 对象
        function sendAJAX(url) {
            return new Promise((resolve, reject) => {
                //1. 创建对象
                const x = new XMLHttpRequest();

                //2. 初始化
                x.open('GET', url);

                //3. 发送
                x.send();

                //4. 事件绑定
                x.onreadystatechange = function () {
                    if (x.readyState === 4) {
                        if (x.status >= 200 && x.status < 300) {
                            //成功啦
                            resolve(x.response);
                        }else{
                            //如果失败
                            reject(x.status);
                        }
                    }
                }
            })
        }
    
        //promise then 方法测试
        // sendAJAX("https://api.apiopen.top/getJoke").then(value=>{
        //     console.log(value);
        // }, reason=>{})
  
        // async 与 await 测试  axios
        async function main(){
            //发送 AJAX 请求
            let result = await sendAJAX("https://api.apiopen.top/getJoke");
            //再次测试
            let tianqi = await sendAJAX('https://www.tianqiapi.com/api/?version=v1&city=%E5%8C%97%E4%BA%AC&appid=23941491&appsecret=TXoD5e8P')

            console.log(tianqi);
        }

        main();

3.Object.values( ) Object.entries( ) Object.getOwnPropertyDescriptors( )

Object.keys()方法返回一个给定对象的所有可枚举键值的数组
Object.values()方法返回一个给定对象的所有可枚举属性值的数组
Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组,返回数组的每个元素又是一个数组
Object.getOwnPropertyDescriptors()方法返回一个给定对象自身可遍历属性的描述对象

 const school = {
            name:"尚硅谷",
            cities:['北京','上海','深圳'],
            xueke: ['前端','Java','大数据','运维']
        };

        //获取对象所有的键
        console.log(Object.keys(school));
        //获取对象所有的值
        console.log(Object.values(school));
        //entries
        console.log(Object.entries(school));
        //创建 Map
        const m = new Map(Object.entries(school));
        console.log(m.get('cities'));

ES9

rest 参数与 spread 扩展运算符

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

ript>
        //rest 参数
        function connect({host, port, ...user}){
            console.log(host);
            console.log(port);
            console.log(user);
        }
	//此时输出为host: '127.0.0.1',
             //port: 3306,
             //user:   username: 'root',password: 'root',type: 'master'
        connect({
            host: '127.0.0.1',
            port: 3306,
            username: 'root',
            password: 'root',
            type: 'master'
        });


        //对象合并
        const skillOne = {
            q: '天音波'
        }

        const skillTwo = {
            w: '金钟罩'
        }

        const skillThree = {
            e: '天雷破'
        }
        const skillFour = {
            r: '猛龙摆尾'
        }

        const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};

        console.log(mangseng)

正则命名分组

便于数据的捕获,实际相当于给没项正则匹配的数据命名(用该命名来存储)

 //通用方法
        //声明一个字符串
        // let str = '<a href="http://www.atguigu.com">尚硅谷</a>';

        // //提取 url 与 『标签文本』
        // const reg = /<a href="(.*)">(.*)<\\/a>/;

        // //执行
        // const result = reg.exec(str);

         console.log(result);//此时输出的对象里group值为undefined
         console.log(result[1]);//输出等于console.log(result.groups.url)
         console.log(result[2]);//同上

        
        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);

正则反向断言

//声明字符串
        let str = 'JS5211314你知道么555啦啦啦';
        //正向断言
        const reg = /\\d+(?=啦)/;
        const result = reg.exec(str);

        //反向断言
        const reg = /(?<=么)\\d+/;
        const result = reg.exec(str);
        console.log(result);

正则扩展-dotAll模式

/dot . 元字符 除换行符以外的任意单个字符

        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>\\s+<a>(.*?)<\\/a>\\s+<p>(.*?)<\\/p>/;
        //dotAll模式 gs为全局匹配
        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);

ES10

数组方法Object.fromEntries( )

Object.fromEntries()将二维数组转换成对象,是Object.Entries()(将对象转换成二维数组)的逆运算

字符串方法 trimStart trimEnd

trim()本来用作去除字符串中的空字符串
trimStart() trimEnd()用作从(左侧)(右侧)位置剔除空字符串

		let str = '   iloveyou   ';
        console.log(str);
        console.log(str.trimStart());//输出 iloveyou     
        console.log(str.trimEnd());//输出      iloveyou

数组方法flat()flatMap()

flat(n)方法将数组降维,参数n为深度(相当于展开层数),默认为1
flatMap()相当于是flat 与 map的结合

Symbol.prototype.description属性

该属性输出symbol的描述符字符串

 //创建 Symbol
        let s = Symbol('尚硅谷');

        console.log(s.description);//输出为尚硅谷

ES11

私有属性:#属性名

案例:私有属性的设置与调用

class Person{
            //公有属性
            name;
            //私有属性#
            #age;
            #weight;
            //构造方法
            constructor(name, age, weight){
                this.name = name;
                this.#age = age;
                this.#weight = weight;
            }

            intro(){
                console.log(this.name);
                console.log(this.#age);
                console.log(this.#weight);
            }
        }

        //实例化
        const girl = new Person('晓红', 18, '45kg');
		//下列方法无法成功,不能用平常方法查看私有属性
        // console.log(girl.name);
        // console.log(girl.#age);
        // console.log(girl.#weight);

        girl.intro();

Promise.allSettled()方法

Promise.allSettled返回值为promise对象,该promise的结果为成功,并且值为数组,每个数组成功的值为每个调用的promise对象的状态与值
Promise.all( )与之类似,区别在于返回的状态与值promise对象的值取决于调用的promise对象的返回值(失败值)

 //声明两个promise对象
        const p1 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品数据 - 1');
            },1000)
        });

        const p2 = new Promise((resolve, reject)=>{
            setTimeout(()=>{
                resolve('商品数据 - 2');
                // reject('出错啦!');
            },1000)
        });

        //调用 allsettled 方法
        // const result = Promise.allSettled([p1, p2]);
        
         const res = Promise.all([p1, p2]);

        console.log(res);

String.matchAll()方法

数据批量匹配方法

        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>/sg

        //调用方法,一次性匹配字符串里符合正则表达式的数据
        const result = str.matchAll(reg);

可选链操作符 ?.

 // ?.
        function main(config){
            // const dbHost = config && config.db && config.db.host;
            //不用层层做判断
            const dbHost = config?.db?.host;

            console.log(dbHost);
        }

        main({
            db: {
                host:'192.168.1.100',
                username: 'root'
            },
            cache: {
                host: '192.168.1.200',
                username:'admin'
            }
        })

动态import

动态import实现懒加载

//常规静态导入
// import * as m1 from "./hello.js";
//获取元素
const btn = document.getElementById('btn');

btn.onclick = function(){
    import('./hello.js').then(module => {
        module.hello();
    });
}

BigInt数据类型

用于大整数表示与运算

//大整形,使用方法:整数后面+n
        // let n = 521n;
        // console.log(n, typeof(n));

        //BigInt函数
        // let n = 123;
        console.log(BigInt(n));//输出123n
        console.log(BigInt(1.2));//报错

        //大数值运算
        let max = Number.MAX_SAFE_INTEGER;
        console.log(max);
        console.log(max + 1);
        console.log(max + 2);//输出和上面输出一致

        console.log(BigInt(max))
        console.log(BigInt(max) + BigInt(1))
        console.log(BigInt(max) + BigInt(2))//大整数只能与大整数型做运算

global.This

始终指向全局对象
ES6面试题集合1
ES6面试题集合2
ES6输入输出题

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号