Es6新特性总结

ES6 新特性

1,let变量声明

  1. 作用:

    • 与var类似, 用于声明一个变量
  2. 特点:

    • 在块作用域内有效
    • 不能重复声明
    • 不会预处理, 不存在提升
  3. 应用:

    • 循环遍历加监听

    • 使用let取代var是趋势

<script type="text/javascript">
    //console.log(age);// age is not defined
    // 声明变量方式
    let age = 12;
    // 1,变量不能重复声明,但是使用var是可以的,为了防止变量重名
    let str = '罗志祥';
    let str = '小猪' //这个会报错
  //  2,块级作用域 
  // let只在代码块中有效,除了{}之外,还有if else while for中国
  {
    let name= 'XXX'  //若使用var来定义,下面是可以读取到值的
  }
  console.log(name)  //这个地方是读取不到的

  // 3,不存在变量提升
  console.log(song)  //会报错,这是不被允许的,但是var变量是可以进行变量提升的
  let song='恋爱达人'
  //4,不影响作用域链
    {
      let school='sss'
      function fn(){
        console.log(school); //是可以进行输出的
        
      } // 循环体中对比
    let btns = document.getElementsByTagName('button');
    for(let i = 0;i<btns.length;i++){
            btns[i].onclick = function () {
           // 如果使用var来定义i的时候,循环之后i就会变成3,没有块作用域的一个概念
           // 但是使用let进行定义i的时候,就会有块作用域的概念,这个i的值就是动态的
              this.style.backgroundColor='pink'
              btns[i].style.backgroundColor='pink'
            }
    }
    // 上面的代码就被分解为
    var i=0  //循环3次之后这里的全局变量i是等于3的
    {
    // 当回调函数被点击的时候,就去上一个作用域里面去找,结果得到的i就是3
    // 为了避免这个情况,最好使用let来声明变量
      btns[i].onclick = function () {
              this.style.backgroundColor='pink'
              btns[i].style.backgroundColor='pink'
            }
    }
    }

</script>

2,const

  1. 作用:

    • 定义一个常量
  2. 特点:

    • 不能修改
    • 其它特点同let
  3. 应用:

    • 保存不用改变的数据
  4. 可以用来声明常量和数组

<script type="text/javascript">
  // 声明常量
    const sex = '男';
    console.log(sex);
  // 1,一定要赋初始值,下面的情况是不允许的
  const sex;
  // 2,一般常量使用大写
    const SEX='XXX'
  // 3,常量的值不能修改
    sex = '女';//不能修改
  // 4,和let一样是块级作用域
  // 5,对于数组对象元素的修改,不算做对常量的修改,不会报错
  // 原因是,从const声明的变量保存的地址值没有改变,那就没有报错
    const TEAN=['ABC','ERT','BUH']
    TEAN.push('MGH')
</script>

3,变量的解构赋值

  1. 理解:
    • 从对象或数组中提取数据, 并赋值给变量(多个)
  2. 对象的解构赋值
    • let {n, a} = {n:‘tom’, a:12}
  3. 数组的解构赋值
    • let [a,b] = [1, ‘atguigu’];
  4. 用途
    * 给多个形参赋值
<script type="text/javascript">
// 对象的解构赋值(常用,一般用于对象的方法调用过多时,为了节省代码量)
    let obj = {name : 'kobe', age : 39};    
    // 一般写法
   let name = obj.name;
   let age = obj.age;
   console.log(name, age);
    // 解构赋值写法
    let {name,age} = obj; //相当于声明的两个变量分别赋值为对象的值
    let{name}=obj  //这种形式也是可以的
    console.log(name) //输出 kobe
    console.log(age); //输出的是39
    //1,不用解构赋值时的缺点案例
     function person(p) {
        console.log(p.name, p.age);//不用时,要这样调用
    }
    person(obj);
    function person1({name, age}) {
     console.log(name, age);//用了之后,可以这样调用
    }
    person1(obj);
    // 2,不用解构赋值时的缺点案例
    obj1={
      name:'hhh',
      age=23,
      setName= function(name){
        this.name=name;
      }
    }
    obj1.setName('uuu') //不用时需要这样写
    let setName = obj
    setName(name)  //用时可以直接写,省略了很多代码量
//数组的解构赋值  不经常用
    let arr = ['abc', 23, true];
    let [a, b, c, d] = arr;
    console.log(a, b, c, d);
</script>

4,模板字符串

(1)声明:

ES6 引入新的声明字符串的方式 ,反引号 ``,常用的符号有’ '," ",单引和双引

(2)内容中可以直接出现换行符,在单引和双引是不可以的

  1. 模板字符串 : 简化字符串的拼接

    • 模板字符串必须用 `` 包含

    • 变化的部分使用${xxx}定义

// 1,内容中可以直接出现换行符
    // 在单引和双引中是不能有换行符的,会报错,要用+进行连接才可以
    let str ='<ul>
                <li>
                  玛丽
                </li>
              </ul>'
    // 对于反引号来说,直接有换行符,是可以的
   let str =`<ul>
                <li>
                  玛丽
                </li>
              </ul>`    
              
// 2,变量拼接
    let loveset='周杰伦'
    let out=`${loveset}是我最喜欢的歌手`;//这样就可以不在用+进行拼接了。

5,简化对象的写法

  • 省略同名的属性值
  • 省略方法的function
<script type="text/javascript">

    let x = 3;
    let y = 5;
    普通额写法
   let obj = {
       x : x,
       y : y,
       getPoint : function () {
           return this.x + this.y
       }
   };
    //简化的写法
    let obj = {
        x,
        y,
        getPoint(){
            return this.x
        }
    };
    console.log(obj, obj.getPoint());
</script>

6,箭头函数

  • 作用: 定义匿名函数

  • 基本语法:

    • 没有参数: () => console.log(‘xxxx’)
    • 一个参数: i => i+2
    • 大于一个参数: (i,j) => i+j
    • 函数体不用大括号: 默认返回结果
    • 函数体如果有多个语句, 需要用{}包围,若有需要返回的内容,需要手动返回
  • 使用场景: 多用来定义回调函数

  • 箭头函数的特点:
    1、简洁
    2、箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在的对象就是它的this
    3、扩展理解: 箭头函数的this看外层的是否有函数,
    如果有,外层函数的this就是内部箭头函数的this,
    如果没有,则this是window。

<script type="text/javascript">
// 1,声明一个函数
  let fun = function () {
       console.log('fun()');
   };
   //没有形参,并且函数体只有一条语句时可以省略花括号
   let fun1 = () => {
    console.log('fun1()');
   }
   let fun1 = () => console.log('fun1()')
    //只要一个形参,并且函数体只有一条语句
    let fun2 = x => x;
    console.log(fun2(5));
    //形参是一个以上
    let fun3 = (x, y) => x + y;
    console.log(fun3(25, 39));//64
    //函数体有多条语句
    let fun4 = (x, y) => {
        console.log(x, y);
        return x + y;
    };
    console.log(fun4(34, 48));//82
    // 定时器函数
    setTimeout(() => {
        console.log(this);
    },1000)
    // 点击事件
   let btn = document.getElementById('btn');
        //没有箭头函数
   btn.onclick = function () {
       console.log(this);//btn
   };
        //使用箭头函数
   let btn2 = document.getElementById('btn2');
   btn.click=()=>{
    console.log(this);//btn
   }
// 2,this是静态的,this始终指向函数所在声明时所在作用域下的this的值
// 无论是谁调用箭头函数,这个函数的this值都不会发生改变
   function getName(){
        console.log(this.name)
   }
   let getName2=()=>{
        console.log(this.name)
   }
    //    设置window对象的name属性
   window.name='window'
   const school ={
       name:'内部方法'
   }
    //    直接调用,都是window来调用的
   getName();  //这里的this也是window
   getName2(); //这里的this也是window
    //  call方法调用
    getName.call(school); //这里的this就是school
    getName2.call(school); //这里的this依旧还是window
// 3,不能作为构造函数,实例化对象
    function Fn(){
        this.name=name;
    }
    //这里可以根据构造函数Fn,来去实例化一个对象
    let fn=new Fn() 
    // 箭头函数,不能作为构造函数去实例化一个对象
    let Fn = ()=>{

    }
// 4,不能使用arguments对象
// 5,箭头函数的实践1,点击div 2s后颜色变化
    // 获取元素
    let ad=document.getElementById('ad')
    // 绑定事件
    // 一般想在定时器中用this进行操作,就会在定时器的外部设置一个变量绑定元素
    ad.addEventListener('click',function(){
        let _this=this
        setTimeout(function(){
            _this.style.background='pink'
        },2000)
    // 可以用箭头函数来实现这种操作,因为这是箭头函数的this就是ad这个元素
    ad.addEventListener('click',function(){
        let _this=this
        setTimeout(()=>{
            _this.style.background='pink'
        },2000)
    })
// 6,箭头函数的实践2 从数组中返回偶数的元素
    // 正常做法
    const arr=[1,4,6,3,2]
    const res =arr.filter(function(item){
        if(item % 2===0){
            return true;
        }else{
            return false;
        }
    })
    // 使用箭头函数
    const res= arr.filter(item => item %2 ===0)

// 7,箭头函数适合场景
// 适合与this无关的问题,比如定时器,数组的方法回调
// 不适合与this有关的回调,事件回调,对象的方法

</script>

7,参数默认初始值

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

  • 1,形参初始值 具有默认值的参数 一般位置要靠后

  • 2,可以和解构赋值相联系

<script type="text/javascript">
// 1,形参初始值 具有默认值的参数 一般位置要靠后
    //定义一个点的坐标
    function Point(x, y=12) {
        this.x = x;
        this.y = y;
    }
// 2,与解构赋值相结合
    function connect({host,username,password=root}){
        console.log(host)
        console.log(username)
    }
    connect({
        host:'localhost',
        username:'root'
    })
</script>

8,rest参数

  • es6引入rest参数,用于获取函数的实参,用来代替arguments
  • rest参数只能放在最后。
<script type="text/javascript">
    function fun(...values) {
    // es5用法
   // 参数是(arguments),伪数组;
    
    // es6用法
        console.log(values);
        values.forEach(function (item, index) {
            console.log(item, index);
        })
    }
    fun(1,2,3);
    // rest参数必须要放到最后
    function fn(a,b,...argus){
        console.log(a)
        console.log(b)
        console.log(args)
    }
    fn(2,3,4,5,6)
    // 输出的是,a:2,b:3,args:[4,5,6]
</script>

9,spread扩展运算符

[…]扩展运算符能将数组转换为逗号分割的【参数序列】

 // ...扩展运算符
    // 声明一个数组
    const boy=['123','345']
    // 声明一个函数
    function fn(){
      // 得到的是一个数组['123','345']
    console.log(arguments)
    // 得到的就是两个参数,0:'123',1:'345'
    // 就等同于把参数序列分开进行传参,就相当于把数组装换为参数列表进行传参
    console.log(...boy)
    }
    // 将数组输入到函数中
    fn(boy)
  • 这里和rest参数不同的是,rest参数是写在定义函数体参数的括号里面的
  • 而这个扩展运算符是放在调用方法时的参数的括号里面的

…运算符的应用:

//  1,数组的合并
    const a=['123','234']
    const b=['78','689']
    //传统的将两个数组进行合并
    const c=a.concat(b) 
    // 使用扩展运算符进行合并
    const c=[...a,...b]

// 2,数组的克隆
    const d=['1','2']
    const e=[...d] //如果d中有引用类型的时候,是一个浅拷贝

// 3,将伪数组转成真正的数组
    const divs=document.querySelectorAll('div')//得到的是一个伪数组
    const Divarr = [...divs];//得到的变量是一个伪数组

10,symbol

  • 概念:

  • ES6中的添加了一种原始数据类型symbol(已有的原始数据类型:String, Number, boolean, null, undefined, 对象)

  • 特点:
    1、Symbol属性对应的值是唯一的,解决命名冲突问题
    2、Symbol值不能与其他数据进行计算,包括同字符串拼串
    3、for in, for of遍历时不会遍历symbol属性。

  • 使用:
    1、调用Symbol函数得到symbol值
    let symbol = Symbol();
    let obj = {};
    obj[symbol] = ‘hello’;
    2、传参标识
    let symbol = Symbol(‘one’);
    let symbol2 = Symbol(‘two’);
    console.log(symbol);// Symbol(‘one’)
    console.log(symbol2);// Symbol(‘two’)
    3、内置Symbol值

    • 除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语

    • 内部使用的方法。

      • Symbol.iterator

             * 对象的Symbol.iterator属性,指向该对象的默认遍历器方法(后边讲)
        
<script type="text/javascript">
    window.onload = function () {
// 创建symbol的方式1
// symbol属性对应的值是唯一的,解决命名冲突问题
      let symbol = Symbol();
      console.log(typeof symbol);
      console.log(symbol);
      let symbol2=Symbol('尚硅谷')
      let symbol3=Symbol('尚硅谷')
      console.log(symbol2 === symbol3)  //返回的是false
// 创建symbol的方式2
      let s4=Symbol.for('字符串') 
      let s5=Symbol.for('字符串') 
      let s6=Symbol.for('字符串')
      console.log(s5 === s6) //返回的是true     
      // 用作对象的属性(唯一)
      let obj = {username: 'kobe', age: 39};
      obj[symbol] = 'hello';
      obj[symbol] = 'symbol';
      console.log(obj);
      for(let i in obj){
        console.log(i);
      }
    }
// 不能与其他数据进行运算,对比和拼接都不可以


</script>
<script>
  // symbol的使用,它对应的值是唯一的,可以向对象中添加方法和属性
  // 当对象的结构很复杂的时候,我们没有办法很容易的查看内部的属性和方法,为了避免命名冲突
  // 我们就可以使用symbol进行添加属性
// 1,添加的方式1
  // 一个未知的对象
  let game={

  }
  // 声明另一个对象
  let methods={
    up:Symbol(),
    down:Symbol()
  }
  // 将值赋值给game中
  game[methods.up]=function(){
    console.log('123')
  }
  game[methods.down]=function(){
    console.log('345')
  }
// 2,添加的方式2
  let youxi= {
      name:'狼人杀',
      [Symbol('say')]:function(){
          console.log('我可以发言')
      }
  }
</script>

11,Symbol内置值

12,迭代器

  • *概念:

  • iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制,任数据结构只要部署了iterator接口,就可以完成遍历操作,

  • 是Symbol的一个属性

  • 作用

    1、为各种数据结构,提供一个统一的、简便的访问接口;

    2、使得数据结构的成员能够按某种次序排列

    3、ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费。

  • 工作原理

    - 创建一个指针对象,指向数据结构的起始位置。

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

    - 接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员

    - 每调用next方法返回的是一个包含value和done的对象,{value: 当前成员的值,done: 布尔值}

    ​ ** value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束。*

    ​ ** 当遍历结束的时候返回的value值是undefined,done值为false*

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

    • 1、Array

      2、arguments

      3、set容器

      4、map容器

      5、String

迭代器的使用:

 const xiyou =['12','34','45']
      // 使用for..of循环数组
      for(let v of xiyou ){
        console.log(v)  //直接是遍历的键值
      }
      for (let i in xiyou ){
        console.log(i)  //这个遍历的是索引号
      }

自定义迭代器案例:

 // 自定义迭代器遍历对象
// 需求:在使用for..of的时候,返回的是stus数组里面的值

      // 声明一个对象
      const banji= {
        name:'终极一班',
        stus:[
          '123',
          '234',
          '344',
          '344'
        ],
        // 自定义迭代器,是根据迭代器的原理来写de
        [Symbol.iterator](){
            let index=0;
            let _this=this
            return {
              next:function(){
                if(index<_this.stus.length){
                  return {
                    value:this.stus[index],
                    done:false
                  }
                  // 下标自增
                  index++
                }else{
                  return{value:undefined,done:true}
                }
              }
            }
        }
      }

13,生成器

  • 概念:(就是一个函数)

    • 1、ES6提供的解决异步编程的方案之一
    • 2、Generator函数是一个状态机,内部封装了不同状态的数据,
    • 3、用来生成遍历器对象
    • 4、可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
  • 特点:

  • 1、function 与函数名之间有一个星号

  • 2、内部用yield表达式来定义不同的状态

  • 例如:

  *function\* generatorExample(){*

 *let result = yield 'hello';  // 状态值为hello*

 *yield 'generator'; // 状态值为generator*

  *}*
  • 3、generator函数返回的是指针对象(接11章节里iterator),而不会执行函数内部逻辑

  • 4、调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true}

  • 5、再次调用next方法会从上一次停止时的yield处开始,直到最后

  • 6、yield语句返回结果通常为undefined, 当调用next方法时传参内容会作为启动时yield语句的返回值。

<script type="text/javascript">
// 1,声明方式

    function * gen(){
      console.log('函数开始执行');
    }
//2,执行方式
    // 调用方式是不同的,这里不会直接打印输出函数开始执行
    let generator = gen()
    // 调用下面的方法才能打印输出 
    generator.next()

// 3,可以在函数体内加上yield语句 
    // yield是作为函数代码的分隔符,是根据next方法来决定执行
    function* generatorTest() {
      console.log('函数开始执行');
      yield 'hello';
      console.log('函数暂停后再次启动');
      yield 'generator';
    }
    // 执行方式
    // 生成遍历器对象
    let Gt = generatorTest();
    // 执行函数,遇到yield后即暂停
    // next()方法执行后,可返回一个值,这个值是yield后面的值和done属性
    console.log(Gt); // 遍历器对象
    let result = Gt.next(); // 函数执行,遇到yield暂停
    console.log(result); // {value: "hello", done: false}
    result = Gt.next(); // 函数再次启动
    console.log(result); // {value: 'generator', done: false}
    result = Gt.next();
    console.log(result); // {value: undefined, done: true}表示函数内部状态已经遍历完毕
    // Gt是一个遍历器对象,可以通过for of来进行遍历
    for (let v of Gt){
      console.log(v) //这时候就会一个一个进行输出
    }



// 4,生成器函数参数
    function * gen(args){
      console.log(args);
      let one = yield 111;
      console.log(one);
      yield 222;
      yield 333;
    }
    // 执行获取迭代器对象
    let iterator = gen('AAA');
    iterator.next() //当执行第一个yeild时,就会打印出AAA这个参数,所以在生成器函数上加上参数是没问题的
    // next()方法也传入实参
    // next()传入的参数是作为上一条yeild返回的结果
    iterator.next('BBB');

// 5,生成器函数实例
    // 异步编程 文件操作,网络操作(ajax,request)数据库操作
    // 定时器的操作案例,需求:1s后在控制台输出 111,然后2s后在控制台输出 222 然后3s后输出333
    // 一般做法,就是定时器里面套定时器,但当异步任务过多的时候,回调太多,就形成一个回调地狱
    //使用生成器函数来做这个效果
    function one(){
      setTimeout(()=>{
        console.log(111);
        iterator.next(); //为了接着执行        
      },1000)
    } 
    function two(){
      setTimeout(()=>{
        console.log(222);
        iterator.next();        
      },1000)
    } 
    function three(){
      setTimeout(()=>{
        console.log(333);
        iterator.next();        
      },1000)
    }
    function * gen(){
      yield one();
      yield two();
      yield three();
    }
    
    // 调用生成器函数
    let iterator = gen();
    iterator.next();//调用gen()第一次

// 6,生成器函数实例2

    // 模拟获取 用户数据 订单数据 商品数据
    function getUser(){
      setTimeout(()=>{
        let data ='用户数据'
        iterator.next(data) //data将作为第一次yield返回的结果
      },1000)
    }
    function getOrder(){
      setTimeout(() => {
        let data='订单数据'
        iterator.next(data)
      }, 1000);
    }
    function getGoods(){
      setTimeout(() => {
        let goods='订单数据'
        iterator.next(data)
      }, 1000);
    }

    function * gen(){
      let userDate = yield getUser()
      console(userDate) //会输出 '用户数据'
      yield getOrder()
      yield getGoods()
    }

14,promise

  1. 概念:

    • Promise对象: 代表了未来某个将要发生的事件(通常是一个异步操作)
    • promise是ES6引入的异步编程的新解决方案。是用来解决回调地狱的解决方法。语法上promise是一个构造函数。
  2. 使用步骤

    * 创建promise对象
        let promise = new Promise((resolve, reject) => {
            //初始化promise状态为 pending
          //执行异步操作
          if(异步操作成功) {
            resolve(value);//修改promise的状态为fullfilled
          } else {
            reject(errMsg);//修改promise的状态为rejected
          }
        })
      * 调用promise的then()
        promise.then(function(
          result => console.log(result),
          errorMsg => alert(errorMsg)
        ))
    
  3. 对象的三个状态

    • ** pending: 初始化状态**
    • *** fullfilled: 成功状态***
    • ** ** rejected: 失败状态*

// 1,promise对象的介绍与基本使用
  // 实例化Promise对象
  const p = new Promise(function(resolve,reject){
    setTimeout(function(){
        // 模拟一个数据
        let data ='数据库中的用户数据'
        // 调用reslove方法,这个p对象的状态就会变成出初始化状态pending
        resolve(data)
        // 调用reject方法,这个p对象就会变成失败状态
    },1000)
  })

  // 初始化状态时,调用promise 的then方法的第一个函数参数
  // 失败状态时,自动调用promise的then方法的第二个函数参数
  p.then(function(value){},function(reason){})

// 2,promise读取文件
const p=new Promise(function(resolve,reject){
    fs.readFile("./resources/为学.md",(err,data)=>{
      // 判断如果失败,直接就调用p.then的第二个参数函数
      if(err) reject(err)
      // 如果成功,直接就调用p.then的第一个参数函数
      resolve(data)
    })
});

p.then(function(value){},function(reason){})

// 3,promise封装ajax

  // 普通操作
  // 1,创建对象
  const xhr = new XMLHttpRequest()

  // 2,初始化
  xhr.open("GET","https://api.apiopen.top/getJoke")

  // 3,发送
  xhr.send();

  // 4,绑定事件,处理响应结果
  xhr.onreadystatechange = function(){
    // 判断
    if(xhr.readyState === 4){
      // 判断响应状态码 200-299
      if(xhr.status >= 200 && xhr.status < 300){
        console.log(xhr.response);
        
      }else{
        // 如果失败
        console.error(xhr.status);
      }

    }
  }
// 使用promise来写
  const p=new Promise((resolve,reject)=>{
    const xhr = new XMLHttpRequest()
    xhr.open("GET","https://api.apiopen.top/getJoke")
    xhr.send();
    xhr.onreadystatechange = function(){
    // 判断
    if(xhr.readyState === 4){
      // 判断响应状态码 200-299
      // 如果是,就代表成功,就调用reslove函数,修改promise的状态码
      if(xhr.status >= 200 && xhr.status < 300){
        resolve(xhr.response);
        
      }else{
        // 如果失败,就调用reject函数,修改promise的状态码
        reject(xhr.status);
      }
    }
  }
  })
  // 指定promise函数的成功和失败的回调
  p.then(function(value){
    console.log(value)
  },function(reason){
    console.log(reason)
  })

</script>

15,promise的then方法

关于promise的then方法

<script>
  // 创建promise对象
  const p = new PromiseRejectionEvent((resolve,reject)=>{
    setTimeout(()=>{
      resolve('用户数据');//设定一个成功的状态
      reject('出错啦') // 设定一个失败的状态
    })
  })
// 调用 then 方法,then方法的返回结果是promise对象,对象状态由回调函数的执行结果决定
// 1,如果回调函数中返回的结果是 非promise类型的属性,状态是成功,返回值为对象的成功的值
// 2,如果回调函数中返回的结果是一个promise对象,那这个返回的promise对象的状态就是p.then的状态

  const p=p.then(value=>{
    console.log(value);
    // 1,返回的是非promise类型的属性
    return '123'
    // 2,返回的是promise对象
    return new Promise((resolve,reject)=>{
      resolve('ok')
    })
     // 3,抛出错误
     throw new Error('出错') //那状态就是失败的状态,值就是'出错'
  },reason =>{})

// then方法可以进行链式调用,一层一层去调用,避免回调地狱的情况
    p.then(value=>{},reason=>{}).then(value=>{},reason=>{})
</script>

16,promise的实践—读取多个文件

// promise实践---读取多个文件
// 类似的情况就是,再返回数据得时候,比如用ajax返回用户id,然后再根据用户id查询其它的数据
// 这种情况就是一层一层的套,这就是回调地狱
// 普通做法:
// 1,引入 fs模块
const fs = require('fs');
const { resolve } = require('path/posix');
const { resourceLimits } = require('worker_threads');
// 2,调用方法读取文件
fs.readFile('js/jquery-1.10.1.min1.js',(err,data1)=>{
     fs.readFile('js/jquery-1.10.1.min2.js',(err,data2)=>{
          fs.readFile('js/jquery-1.10.1.min3.js',(err,data3)=>{
               
          })
     })
})


// 使用promise 实现
const p = new Promise((resolve,reject)=>{
     fs.readFile('路径1',(err,data)=>{
          resolve(data);
     })
})

p.then(value=>{
     console.log(value) //这里的value的值就是data
     // 为了再进行一次读取文件,就让其返回一个promise对象
     return new Promise(value=>{
        fs.readFile('路径2',(err,data)=>{
     //     value是一个文件里的内容,data是第二个文件里面的内容,可以将其作为一个文件的合并
     //     这里返回的promise的值就是p.then返回的值,并且状态也是一样的 
          resolve([value,data])
     })  
     })    
}).then(value =>{
     // 这里的value就是上一个返回的[value,data]
     fs.readFile('路径3',(err,data)=>{
     //     压入
     value.push(data)
     resolve(value)
     })
}).then(value =>{
     // 这里的value就是三个文件中的内容
     console.log(value)
})

17,promise --catch方法

<script>
  // promised的catch方法
  // 就是设置一个失败回调的方法
  const p = new Promise((resolve,reject)=>{
    setTimeout(() => {
      // 设置p对象的状态为失败,并设置失败的值
      reject('出错啦')
    }, 1000);
  })
  // 1,使用p.then方法
  p.then(function(value){},function(reason){
    console.error(reason)
  })

  // 2,使用catch方法
  p.catch(function(reason){
    console.warn(reason);
  })
</script>

18,set

新的数据结构set(集合),类似于数组,但成员都是唯一的,集合实现了iterrator接口,所以可以使用【扩展运算符】和【for…of】进行遍历

  • 容器: 能保存多个数据的对象, 同时必须具备操作内部数据的方法
  • 任意对象都可以作为容器使用, 但有的对象不太适合作为容器使用(如函数)

set的特点:保存多个value, value是不重复 ====>数组元素去重

API:

  • Set()/Set(arr) //arr是一维数组
  • add(value) //往set添加一个元素
  • delete(value) //从set里删除一个元素
  • clear(); //清除set里的内容
  • has(value) // 确定set里面有没有某个元素
  • size // 返回
 <script>
          let s=new Set()
          let s1=new Set(['大事','小事'])

          // 实践
          let arr =[1,2,3,42,2,4];
     // 1,数组去重
          // 先将arr的内容存进set,因为set是一个不重复的数组
          // 然后再将set装换成数组
          let res=[...new Set(arr)]
     // 2,交集
          let arr2=[4,6,2,7,4];
          // filter是数组的遍历结果 
          let res=[...new Set(arr)].filter(item =>{
               let s2 = new Set(arr2);//s2是arr2去重后的数组
               if(s2.has(item)){
                    return true
               }else{
                    return false
               }
          })
     // 3,并集
     let union =[...arr,...arr2];//先将两个数组进行合并
     let res=[...new Set(union)];//然后设置为set,自动去重
     // 4,差集
     let diff=[...new Set(arr).filter(item =>! (new Set(arr2).has(item)))];
     </script>

19 ,Map

  • Map数据结构,类似于对象,也是键值对的集合。但是键的范围不局限于字符串,各种类型的值(包括对象都可以当做键)。
  • Map也实现了iterator接口,座椅可以使用扩展运算符和【for…of】进行遍历。
  • map的特点: 保存多个key–value, key是不重复, value是可以重复的

API:

  • Map()/Map(arr) //arr是二维数组
  • set(key, value)
  • delete(key)
  • clear()
  • has(key)
  • size
<script>
          // 声明map
          let m= new Map();
          // 添加元素
          m.set('name','wlijun');
          m.set('change',function(){
               console.log('change you');                           
          })
          let key={
               school:'ncut'
          }
          m.set(key,['北京'])
          // 删除
          m.delete('name')
          // 查看
          console.log(m.get(key));
          // 清空
          // m.clear
          // 遍历
          for(let v of m){
               console.log(v)
          }
</script>

20,class类

通过class关键字,可以定义类,用来实例化一个对象。

对于class能做到的东西,es5都可以做到,新的class的写法只是让对象原型的写法更加清晰,更像面向对象变成的语法而已。

(1)class声明类
(2)constructor定义构造函数初始化
 class Person {
        //调用类的构造方法,constructor 不能修改
        constructor(name, age){
            this.name = name;
            this.age = age;

        }
        //定义一般的方法,必须要这样定义
        showName(){
            console.log(this.name, this.age);
        }
    }
    let person = new Person('kobe', 39);
    console.log(person, person.showName());
(3)extends继承父类
(4)super调用父类构造方法
// 继承
    // 举例es5
    // 父类
    function Phone(brand,price){
        this.brand=brand;
        this.price=price;
    }
    Phone.prototype.callOther = function(){
        console.log('我可以打电话')
    }
    function SmartPhone(brand,price,color,size){
        Phone.call(this,brand,price);
        this.color = color;
        this.size = size;
    }    
    // 设置自己构造函数的原型
    SmartPhone.prototype = new Phone;
    SmartPhone.prototype.constructor =SmartPhone;
    // 声明子类的方法
    SmartPhone.prototype.photo = function(){
        console.log('我可以拍照')
    }
    SmartPhone.prototype.play=function(){
        console.log('我可以玩')
    }
    // 实例化子类的实例对象
    const chuizi = new SmartPhone('锤子',2499,'黑色','5.5');
    // 里面是有父类的方法的
    console.log(chuizi)
   
// class类的方法  
    // 父类
    class Person {
        //调用类的构造方法,constructor 不能修改
        constructor(name, age){
            this.name = name;
            this.age = age;

        }
        //定义一般的方法,必须要这样定义
        showName(){
            console.log(this.name, this.age);
        }
    } 
     //定义一个子类
    class StrPerson extends Person{
        constructor(name, age, salary){
            super(name, age);//调用父类的构造方法
            this.salary = salary;
        }
        showName(){//在子类自身定义方法
            console.log(this.name, this.age, this.salary);
        }
    }
    let str = new StrPerson('weide', 38, 1000000000);
    console.log(str);
    str.showName();
(5)static定义静态方法和属性
// 静态成员
    // 举例,用es5
    function Phone(){
    }
    // 这里的属性和方法是属于函数的,被称为静态成员
    Phone.name= '手机'
    Phone.change=function(){
        console.log('...')
    }
    Phone.prototype.size='123';
    // 这里的ip实例对象是不能调用构造函数的name属性和change方法的
    // 实例对象和函数对象的属性和方法是不相通的。
    // 这里的实例对象是和构造函数Phone的ProtoType上的属性是相通的。
    let ip = new Phone();
    // 这两个是不可调用的
    // ip.change()
    // let name=ip.name
    // 下面的这个是可以调用的
    ip.size();

    // class的静态属性
    class shouji{
        // 静态属性
        // 用static声明的属性和变量只属于类,而不属于实例对象
        static name ='手机'
        static change(){
            console.log('改变世界');
        }
    }
(6)父类方法可以重写

子类可以重写父类的方法

比如父类有一个方法是call(),那父类就可以重新定义这个call() 方法

// class类的方法  
    // 父类
    class Person {
        //调用类的构造方法,constructor 不能修改
        constructor(name, age){
            this.name = name;
            this.age = age;

        }
        //定义一般的方法,必须要这样定义
        showName(){
            console.log(this.name, this.age);
        }
    } 
     //定义一个子类
    class StrPerson extends Person{
        constructor(name, age, salary){
            super(name, age);//调用父类的构造方法
            this.salary = salary;
        }
        showName(){//在子类自身定义方法
            console.log(this.name, this.age, this.salary);
        }
        // 重写父类的同名方法,当子类的实例对象调用call方法时,就是调用自身重写的方法
        // 这样就没有办法去调用父类的同名方法了
        call(){
            console.log('我是重写的方法');
        }
    }
    let str = new StrPerson('weide', 38, 1000000000);
    console.log(str);
    str.showName();

19,数值扩展

<!--
0,Number.EPSILON是js表示 的最小精读,使用在浮点数运算上面
1. 二进制与八进制数值表示法: 二进制用0b, 八进制用0o
2. Number.isFinite(i) : 判断是否是有限大的数
3. Number.isNaN(i) : 判断是否是NaN
4. Number.isInteger(i) : 判断是否是整数
5. Number.parseInt(str) : 将字符串转换为对应的数值
6. Math.trunc(i) : 直接去除小数部分
-->
<script type="text/javascript">

  // Number.EPSILON
  // 对于浮点数的运算 0.2+0.1是不完全等于0.3的,所以在我们处理的时候,就可以封装一个函数
  function equal(a,b){
    if(Math.ads(a-b) <Number.EPSILON){
      return true
    }else{
      return false
    }
  }
    console.log(equal(0.1+0.2,0.3))//则返回true
    // 二进制和八进制
    console.log(0b1010);//10
    console.log(0o56);//46
    //Number.isFinite(i) : 判断是否是有限大的数
    console.log(Number.isFinite(NaN));//false
    console.log(Number.isFinite(5));//true
    //Number.isNaN(i) : 判断是否是NaN
    console.log(Number.isNaN(NaN));//true
    console.log(Number.isNaN(5));//falsse

    //Number.isInteger(i) : 判断是否是整数
    console.log(Number.isInteger(5.23));//false
    console.log(Number.isInteger(5.0));//true
    console.log(Number.isInteger(5));//true

    //Number.parseInt(str) : 将字符串转换为对应的数值
    console.log(Number.parseInt('123abc'));//123
    console.log(Number.parseInt('a123abc'));//NaN

    // Math.trunc(i) : 直接去除小数部分
    console.log(Math.trunc(13.123));//13



</script>

20,对象扩展

1,Object.is 判断两个值是否完全相等

2,Object.assign 对象的合并

3,Object.setPrototypeOf Object.getPrototypeof 设置原型对象

<script type="text/javascript">
    // Object.is 判断两个值是否完全相等,它的功能和==类似,但也有区别
    console.log(Object.is('abc', 'abc'));//true
    console.log(NaN == NaN);//false
    console.log(Object.is(NaN, NaN));//true

    console.log(0 == -0);//true
    console.log(Object.is(0, -0));//false

    //Object.assign(target, source1, source2..)
    let obj = {name : 'kobe', age : 39, c: {d: 2}};
    let obj1 = {};
    // 意思就是后面的把前面的进行覆盖
    // 覆盖的是什么呢,是相同属性名会覆盖值,如果没有相同的属性名,那将不会覆盖
    Object.assign(obj1, obj);
    console.log(obj1, obj1.name);

    //直接操作 __proto__ 属性
    let obj3 = {name : 'anverson', age : 41};
    let obj4 = {};
    obj4.__proto__ = obj3;
    console.log(obj4, obj4.name, obj4.age);
  // 设置原型对象  Object.setPrototypeof(s1,s2),设置s1的原型对象是s2
  const school = {
    name:'尚硅谷'
  }
  const cities ={
    xiaoqu:['北京']
  }
  Object.setPrototypeOf(school,cities);
  console.log(school)

</script>

21,模块化

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

  • 好处:

1,防止命名冲突(js文件是互不干扰的)。2,代码复用(一个功能性的接口,可以供其他很多地方使用)3,高维护性

  • 模块化规范产品:

    • es6之前的模块化规范有:

      • commonJS ----NodeJs,Broserify

      • AMD ----requireJs

      • CMD------seaJS

    • es6的模块化规范

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

    • //m1.js
      
         // 如果想向外面暴露数据,用export关键字
         //1,分别暴露数据    
      export let school ='尚硅谷'
      export function teach(){
           console.log('我们可以教给你开发技能');
      }
         // 2,统一暴露数据
      let school ='尚硅谷'
      function teach(){
          console.log('我们可以教给你开发技能');
      }
      export{school,teach}
          // 3,默认暴露
      export default{
           school:'****',
           teach:function(){
                console.log('***')
           }
      }
      
      //module.html
         <!-- 相对于之前使用js文件的引入的方式是不同的 -->
      <script type="module">
          // 引入m1.js 模块内容
          // 这时候,m1.js里面暴露的变量就都存进了m1里面
          import * as m1 from "m1.js";
      	//1.当js文件中是用分别暴露和统一暴露的时候,调用数据的方式是:
      	m1.teach()
      	//2,当js文件中是用默认方式进行暴露的时候,调用数据的方式是:
      	m1.default.teach()
      </script>
      
    • 使用script标签引入模块数据算法

      • // 1,通用方式
            import * as m1 from "m1.js";
        
            // 2,解构赋值的方式
            import {school,teach} from "m1.js";
                // 如果有重名的话,可以起一个别名
            import {school as guigu,teach as teach1} from "m1.js"
                console.log(guigu,teach1);
                // 针对js中默认暴露的变量,引入的方式
                // 这里的default必须要 起一个别名才可以,不能直接使用
            import {default as m3} from "m1.js"
            // 3,简便形式,只针对默认暴露的模式
            import m3 from "m1.js"
            console.log(m3)
        
    • 浏览器使用ES6模块化的方式二

      //modele.js
      // 如果在html里面的script标签里面引入模块
      // 并且调用接口,会造成代码体积非常的大
      // 所以可以把引入模块的代码全都放在一个js文件里
      // 然后在html里面引入这个js文件即可
      import * as m1 from "m1.js"
      import * as m2 from "m1.js"
      import * as m3 from "m1.js"
      
      // Module.html
      
      <script src="moduel.js" type="module"></script>
      <script>
          console.log(m1)
          console.log(m2)
          console.log(m3)
      </script>
      
      
    • 在项目中使用这个ES6,模块化代码

      • 由于浏览器的兼容性,并不是所有的浏览器都能使用上面的方式引入模块。
      • 于是可使用Bable进行模块化代码的装换,将es6模块化代码装换成es5代码,然后再进行引用
      • 步骤:
      • 1,安装工具 bable-cli,bable-preset-env,browserify(webpack)
      • 2, npx babel src/js -d dist/js --presets=bable -preset -env(就是将src/js下面的js文件装换到dist/js 目录里面)
      • 3,打包 npx browserify ist/js/app.js -o dist/bundle.js
      • 4,在讲打包好的js文件,引用在html里面,就可以正常的使用啦

es7新特性

1,Array.prototype.includes

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

和indexOf相比,是indexOf,如果 存在就返回数组下标,如果不存在就返回-1,而includes是返回的true/false

2,指数操作符

2的10次方,就写成 2** 10,和Math.pow(2,10)

es8新特性

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

1,async

  • 概念:

    • 1,async函数的返回值为promise对象

    • 2,promise对象的结果是由async函数执行的返回值决定的

      • // async 函数
            async function timeout(ms) {
              // 这里的返回值可以是字符串,或者其他类型的值,但是最终这个函数返回的就是一个promise对象
              // 如果返回值不是设置的promise对象,那这个函数的返回的promise对象的状态就是成功的,并且值就是设置的返回的值
              // return 'zifuchuang' 
              // 如果在函数体中,抛出一个错误,那么返回的promise对象就是一个失败的状态
              throw new Error('出错啦')
               // 如果返回值是设置的promise对象,那这个函数返回的对象就是设置的返回的promise对象,其状态是一致的。
              return new Promise(resolve => {
                setTimeout(resolve, ms);
              })
            }
        

    2,await表达式

    • await必须写在async函数中
    • await右侧的表达式一般为promise对象
    • await返回的是promise成功的值
    • await的promise失败了,就会抛出异常,需要 通过try…catch捕获处理
    // 一个成功的promise对象
        // 手动创建一个promise对象
        const p1 = new Promise((resolve,reject)=>{
          resolve('用户的数据')
        })
        // await要放在async函数中
        async function main(){
          // await 返回的是右侧promise对象成功的值
          let res=await p1;
          console.log(res)
        }
        main()//调用 main函数,返回的值就是'用户的数据'
    
    // 一个失败的promise对象
        const p2 = new Promise((resolve,reject)=>{
          reject('失败的数据')
        })
        
        async function p2Err(){
          try{
          //如果得到的是一个失败的promise,那么就要用try..catch来进行捕获
            let res=await p2Err;
            console.log(res);
          }catch(e){
            console.log(e)
          }
        }
    
    

3,async和await相结合

案例1:

// async和await相结合进行异步任务

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

// 读取第一个文件
function readfirst(){
     fs.readFile('路径',(err,data)=>{
          // 如果失败
          if(err) reject(err)
          // 如果成功
          resolve(data)
     })
}
function readsecond(){
     fs.readFile('路径',(err,data)=>{
          // 如果失败
          if(err) reject(err)
          // 如果成功
          resolve(data)
     })
}
function readtirth(){
     fs.readFile('路径',(err,data)=>{
          // 如果失败
          if(err) reject(err)
          // 如果成功
          resolve(data)
     })
}
// 声明一个 async函数
async function main(){
     // 获取三个文件中的内容,得到的就是上面方法,读取到的数据
     let first=await readfirst()
     let second=await readsecond()
     let tirth =await readtirth()

     console.log(first+second+tirth);

}

案例2:

 // 模拟ajax请求,返回的结果是promise对象
    function sendAJAX(url){
      // 为了得到一个promise对象类型的返回值
      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)
    },reson=>{})

    // asncy和await结合测试
    async function main(){
      let res=await sendAJAX('https://api.apiopen.top/getJoke')
      console.log(res)
    }

4,对象扩展

  • Object.values()方法返回一个给定对象的所有可枚举属性值的数组
  • Object.entries()方法返回一个给定对象自身可遍历属性[ key,value] 的数组
<script>
  const school={
    name :"尚硅谷",
    cityies:['北京','上海'],
    xueke:['前端','java']
  }
  // 获取对象所有的键
  console.log(Object.keys(school));
  // 获取对象所有的值
  console.log(Object.values(school));
  // entries 返回对象自身可遍历的[key,value]值,这样是方便创建一个对象
  const m = new Map(Object.entries(school))
// 返回对象属性的描述对象
console.log(Object.getOwnPropertyDescriptor(school))
</script>

es9新特性

1,扩展运算符和rest参数

rest参数与spread扩展运算符在es6中已经引入,不过在es6中只针对数组

在es9中为对象提供了像数组一样的rest参数和扩展运算符

<script>
          // rest参数的使用
          // 传来的前两个参数是存放在前两个参数里面,其他参数是存在user里面
          function  connect ({host,port,...user}){
               console.log(host)
               console.log(port)
               console.log(user)
          }
          connect({
               host :"localhost",
               port : 3306,
               username:'wlijun',
               pwd:'root'
          })
          // spread运算符
          // spread运算符对对象的操作
          const skillone ={
               a:'000',
               b:'222'
          }
          const skilltwo ={
               a:'111',
               d:'222'
          }
          // 输出对象的属性和方法
     //     ...skillone  //a:'000',b:'222'
          // 使用运算符可以将两个对象放在同一个对象里面
          // 如果有重名的,会进行值的覆盖
          const skill={...skillone,...skilltwo}
          console.log(skill)
     </script>

2,正则扩展-命名捕捉数组

<script>
          // 之前的做法
          // 声明一个字符串
          let str ='<a href="路径">尚硅谷</a>'
          // 提取url 与标签文本
          const reg=/<a href="(.*)">(.*)<\/a>/;
          // 执行
          // 返回的内容第一条是整个字符串,第二条是第一个(.*)的内容,第三条是第二个(.*)的内容
          const res =reg.exec(str);
          console.log(res[1])
          console.log(res[2])

          // 扩展的做法
          let str ='<a href="路径">尚硅谷</a>'
          const reg=/<a href="(?<url>.*)">(?<text>.*)<\/a>/
          const res = reg.exec(str)
          // 这里的res里面有groups属性,里面包含了url和text信息
          console.log(res.groups.url)
          console.log(res.groups.text)
     </script>

3,正则扩展 dotAll模式

<script>
          //  dot . 元字符 除换行符以外的任意单个字符
          // 需求,就是将下面的数据提取出来,保存成一个对象
          let str=`
               <ul>
                         <li>
                         <a>肖兴克的救赎</a>
                         <p>上映日期:</p>
                         </li>
                         <li>
                         <a>肖兴克的救赎</a>
                         <p>上映日期:</p>
                         </li>
                    </ul>
          `
          // 因为str中有换行符,所以在使用正则的时候,要把\s加上
          const reg=/<li>\s+<a>(.*?)<\/a>\s+<\/li>/
          // 在使用dot .的时候
          const reg= /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs
          // 想获得多个li中的标签的值,使用循环
          let res;
          let data=[]
          while (res = reg.exec(str)){
               console.log(res)
               data.push({title:res[1],time:res[2]})
          }
          console.log(data)
     </script>

es10

1,对象扩展,Object.fromEntries

<!-- 1,Object.fromEntries 用来创建一个对象,它的参数接收二维数组和map-->
     <script>
          // 参数是二维数组
          const res=Object.fromEtries([
               ['name','尚硅谷'],
               ['xueke','java,大数据,前端,云计算']
          ]);
          // 参数是Map
          const m =new Map();
          m.set('name','尚硅谷')
          const res = Object.fromEtries(m);
     // 和es8里面的Object.entries方法是逆运算,这个方法是把一个对象装换成二维数组
     
     </script>

2,字符串扩展方法(trimStrat与trimEnd)

<!-- trim字符串扩展 -->
     <script>
          // trimStart清除字符串左侧的空白字符
          // trimEnd清除字符串右侧的空白字符
          const str='    i love you   '
          console.log(str.trimStart())
          console.log(str.trimEnd())
     </script>

3,数组扩展方法(flat和flatMap)

<script>
          // falt 将一个多维数组转换为低维数组
          const arr=[1,2,3,[5,6]]
          console.log(arr.flat())//输出为[1,2,3,4,5,6]
          // 参数为深度,是一个数字,默认是1
          // 将一个三维数组转换成二维数组
          const arr3=[1,2,[3,4,[5,6]]]
          console.log(arr3.flat(2))// [1,2,[3,4,5,6]]

          // flatMap
          const arr=[1,2,3]
          // 就是将数组里所有的返回结果都乘以10
          const res =arr.Map(item=>item*10);
          console.log(res) //[10,20,30]

          // 当arr数组是一个二维数组的时候,上面的item里面返回的是一个数组,那输出的res就是一个二维数组
          // 这时候就可以用flatMap,直接将返回结果降低为一维数组。
          const res1=arr.flatMap(item =>[item*10])
     </script>

4,symbol扩展Symbol.prototype.description

<!-- symbol扩展Symbol.prototype.description -->
     <script>
          // 用来获取字符串的描述
          // 创建一个Symbol
          let s =Symbol('尚硅谷')
          console.log(s.description) //尚硅谷
     </script>

es11新特性

1,私有属性

<script>
          class Person{
               // 共有属性
               name;
               // 私有属性
               #age;
               // 构造方法
               constructor(name,age){
                    this.name=name;
                    this.#age = age;
               }
               intro(){
                    console.log(this.name)
                    console.log(this.age)
               }
          }
          // 实例化
          const girl = new Person('小红',18);
          console.log(girl) //
          console.log(girl.name) //可以输出
          console.log(girl.#age) // 不可以输出,要在类内部进行使用
          girl.intro() //直接调用类里面的方法,可以将age进行输出
     </script>

2,promise.allSettled方法

<script>
          // 这个方法接收promise数组,返回的是promise对象,
          // 返回的结果一直是一个成功的状态,返回结果的值是promise对象数组,
          // 数组里面是获取到promise对象的状态和对应的值

          // 声明了两个promise对象
          const p1 = new Promise((reslove,reject)=>{
               setTimeout(()=>{
                    reslove('成功啦')
               },1000)
          })
          const p2 = new Promise((reslove,reject)=>{
               setTimeout(()=>{
                   reject('失败了')
               },1000)
          })
          // 调用了 allsettied方法
          const result =Promise.allSettled([p1,p2]);
          console.log(result)
          // all
          const res = Promise.all([p1,p2]);
          // 和上面不同的是,当p1和p2是成功的状态的时候,res才是一个成功的状态,否则就是失败的状态
          // 而且返回值也是不相同的,就是当p1或p2是失败的状态,res就返回失败的peomise对象的值
          console.log(res)

          // 两者不同是,如果需要两个promise都成功的话,才能往下进行,那就使用all
          // 如果是不管成功失败都能往下进行,或者可以得到两者的值,那就用allSettled方法
     </script>

3,matchAll方法

<!-- matchAll方法  可批量提取数据-->
     <script>
          let str=`
               <ul>
                         <li>
                         <a>肖兴克的救赎</a>
                         <p>上映日期:</p>
                         </li>
                         <li>
                         <a>肖兴克的救赎</a>
                         <p>上映日期:</p>
                         </li>
                    </ul>
          `
          // 声明正则
          const reg =  /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg
          // 调用方法,
          const res = str.matchAll(reg);//返回的结果是一个可迭代对象,有一个next方法,可用for of循环
          for(let v of res){
               console.log(v)
          }
          const arr = [...res] //转换成数组,就可以得到全部的结果啦

     </script>

4,可选链操作符

 <!-- 可选链操作符 -->
     <script>
          // 形式?.
          function main(config){
               // 当我们要获取db里面的username的时候
               // 要进行判断config是否传进来,config里面是否有db属性等
               const dbHost =config && config.db && config.db.host
               // 当时使用可选链操作符的时候,可以直接写,如果没有传进来参数,也不会报错,会返回undefined
               const dbhist=config?.Person?.host
          }

          main({
               db:{
                    host :'***',
                    username:'***',
               }
          })
     </script>

5,动态import

<!-- 动态import -->
     <script>
          // 对js模块进行按需加载
          // 当点击这个按钮的时候,才导入某一个模块,引用里面的方法
          // 获取元素
          const btn = document.getElementById('btn');
          // ***.js
          export function hello (){
               console.log('hello')
          }
          btn.onclick = fucntion(){
               // import返回的对象是一个promise对象,这个对象返回的就是js模块中暴露出来的方法
               import('**.js').then(module =>{
                    module.hello();
               })
          
          }
     </script>

6,BigInt 大整数

<!-- BigInt大整形 -->
     <script>
          //数字后面加上n的意思就是表示这个数是一个大整形
          let n = 521n;
          // 大整形函数
          let n1= 123
          console.log(BigInt(n1))  //123n
          
          // 大数值运算
          // 对于number来说,到达一个最大值,再相加的时候,就会出问题
          // 所以对于很大的数值,就可以用大整形
          let max =Number.MAX_SAFE_INTEGER;
          // 这里的大整形是不能和整型相加的,都需要装换成大整形
          console.log(BigInt(max)+BigInt(1))
     </script>

7,绝对全局对象

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值