ES6 ~ ES*

276 阅读12分钟

不经一番寒彻骨,怎得梅花扑鼻香。要耐心看下去哦!相信你终有所得!

ES6

Let Const 定义

let的使用:

  1. 变量不能重复声明(var可以) ;
  2. 块级作用域;
  3. 存在变量提升(在定义语句之前使用变量,var可以)存在这个过程,但是结果是不赋值的;
  4. 不影响作用域链效果(可闭包);

const的使用:

  1. 一定要赋初始值,否则报错;
  2. 定义的常量为大写(潜规则);
  3. 常量的值不能修改;
  4. 块级作用域;
  5. 对数组和对象内属性的修改不算对常量的修改(指向的地址没改变);

注: 在没定义使用变量时,报语法错误; 在定义但没初始化时默认赋值undefined; 赋值为null时,既没指向也没值,输出为null,所以当声明不确定的变量时,尽量写null;

解构赋值

  1. 数组解构([ ])
let F4 = ['刘能','赵四','宋小宝','小沈阳'];

let [liu, zhao, song, xiao] = F4;
  1. 对象解构({})
let team = null
const ZHAO = {
    name: '赵本山',
    age: '*',
    team: 'F4',
    skill: {
        song: '',
        dance: '',
        rap: '',
    },
    xiaoPin() {
        console.log(this)
    },
}
/**
 * sex = '明白'  ----  给解构的变量设置默认值
 * age:localtion ---- 解构对象属性赋值给不同名变量
 * skill:{song, dance, rap} ---- 嵌套对象的解构
 */
// ({team} = ZHAO);
let {name, sex = '明白', xiaoPin, age: localtion,skill: { song, dance, rap }} = ZHAO
console.log(team)
console.log(name)
console.log(sex)
xiaoPin() // window
// console.log(age); //age is not defined
console.log(localtion)
// console.log(skill); // skill is not defined
console.log(song, dance, rap) // ''         

注: 深浅拷贝取决于变量的内部属性,如内部属性为基础数据类型则为深拷贝,否则为浅拷贝; this的指向变了;不是顺序赋值,是同名赋值;

模板字符串(`` , ${})

  1. 声明;
  2. 可以直接换行,不用换行符(\n);
  3. 变量拼接;

简写对象

  1. 简写键值对
let name = '钱';
let fun = () =>{ }

let obj = {
  name,
  fun
}
  1. 在对象中简写方法(去掉了function)
const OBJ ={
  fun2(){}
}

箭头函数

  1. 声明一个函数,省略写法和箭头写法不是一个东西,省略写法的this没变
let fun = function() {};

function fn() {};

let fun = () =>{ };
  1. this是静态的,始终指向函数声明时所在的作用域的this值,用call也改不了;
  2. 不能作为构造函数实例化对象;
  3. 不能使用arguments变量;
  4. 箭头函数的简写, 省略小括号(有参数且只有一个参数)和花括号(有一行js代码);
  5. 只有一行语句,可省略大括号和return,自动return。

函数的参数

  1. 形参初始值
function add(a, b, c=10){ }
  1. rest参数获取实参(es5 为 arguments), 与es5的不同是这个可以使用这些数组方法
function add(...args) {
    console.log(args)  // fifter、map、every、some 
}
add(1,2,3,4)

arguments和 rest的区别:

  1. arguments是伪数组, args是真数组;
  2. args是自己起的名,可以随便叫, arguments不行;
  3. args必须写在括号中,且放到最后面,否则报语法错误;
  4. arguments包含所有传进来的参数值, rest只包含未被命名的参数值;

扩展运算符(...)

转化为参数序列,用','分开

let F4 = ['刘能', '赵四', '宋小宝', '小沈阳'];

const ZHAO = ['赵本山', ...F4]; //['赵本山', '刘能', '赵四', '宋小宝', '小沈阳']

应用: 数组的合并、克隆,将伪数组转化为真数组;

注: 如果扩展的数组中有 引用类型的参数 , 那么此拷贝为浅拷贝

symbol数据类型

  1. 值是唯一的,可以用来解决命名冲突问题(我们不可见);
  2. symbol值不能与其他类型进行运算;
  3. symbol的对象属性不能用 for... in 进行循环,但是可以用reflect.ownKeys来获取对象的所有键名;
  4. symbol具有11个内置 属性
1. 自动随机
let sym = Symbol();
2. 描述字符串,并不是symbol的值,每次返回的值也不是一样的;下面两个变量虽然一样,但是值并不一样
let sym = Symbol('随机且不重复的数')
let sym = Symbol('随机且不重复的数')
3.下面两个变量是一样的,返回值也一样;for的情况下在全局作用域内进行搜索;
let sym = Symbol.for('随机且不重复的数')
let sym = Symbol.for('随机且不重复的数')

迭代器与生成器(async 与 await的原生)

迭代器(iterator接口)

1、推荐在循环对象属性的时候使用 for...in,在遍历数组的时候的时候使用 for...of

2、for...in 循环出的是 key,for...of 循环出的是 value

3、注意,for...of 是 ES6 新引入的特性。修复了 ES5 引入的 for...in 的不足

4、for...of 不能循环普通的对象(如通过构造函数创造的),需要通过和 Object.keys()搭配使用

forlet item of obj){ }   // item 为键值或元素

forlet item in obj) { }  // item 为键名或索引
  1. 工作原理

创建一个指针对象,指向当前数据结构的起始位置 第一次调用对象的next方法,指针自动指向数据结构的第一个成员; 接下来不断调用next方法,指针不断向后移,直到指向最后一个; 每调用next方法返回一个包含value和done属性的对象;

        const F4 = {
          name: '赵家班',
          member: ['刘能', '赵四', '宋小宝', '小沈阳'],
          [Symbol.iterator](){
            let index = 0;
            return{
              next:() =>{
                if(index < this.member.length){
                  let result ={value: this.member[index], done: false}
                  index ++ ;
                  return  result ;
                }else{
                  return {value: undefined, done: true}
                }
              }
            }
          }
        }
        
        for(let m of F4){
          console.log(m)  // 刘能  赵四 宋小宝 小沈阳
        }

自定义对象要想到迭代器

生成器(generator)

定义:一个特殊的函数 声明特殊,调用特殊。与迭代器连用

  1. yield: 分割一个单独的作用域
     function * gen(){
       console.log(1);
       yield `我来分割`;
       console.log(2);
       yield '我也来';
       console.log(3);
     }
    
     let iterator = gen();
    //  iterator.next();  // 输出1
    //  iterator.next();  // 输出2
    //  iterator.next();  // 输出3
     console.log( iterator.next()); //输出 1  {value: '我来分割', done: false}
     console.log( iterator.next()); //输出 2  {value: '我也来', done: false}
     console.log( iterator.next()); //输出 3  {value: undefined, done: true}

     for(let v of gen()){
        console.log(v)  // 输出 1 我来分割 ...
     }
  1. 生成器函数参数的传递 参数依次往前提,当做前一个yield的值,可以在后面使用
    function * gen(arg){
       console.log(arg);
       let A = yield `我来分割`;
       console.log(A);
       let B = yield '我也来';
       console.log(B);
     }
    
     let iterator = gen('AAA');
     console.log( iterator.next('BBB')); //输出 AAA {value: '我来分割', done: false}
     console.log( iterator.next('CCC;)); //输出 BBB  {value: '我也来', done: false}
     console.log( iterator.next('DDD')); //输出 CCC  {value: undefined, done: true}

  1. 异步编程的实用 解决回调地狱
      let n = 0;
      function one(){
        setTimeout(() =>{
          console.log(n++);
          iterator.next()
        }, 1000)
      }
      function two(){
        setTimeout(() =>{
          console.log(n++);
          iterator.next()
        }, 1000)
      }
      function three(){
        setTimeout(() =>{
          console.log(n++);
          iterator.next()
        }, 1000)
      }
      function * gen(){
        yield one();
        yield two();
        yield three();
      }

      let iterator = gen();
      iterator.next()

模拟获取用户数据 => 获取订单数据 => 获取商品数据

将上一次的值通过next传参就能获取上一次得到的值

Set集合

定义:类似于数组,但每个成员都是唯一的;且集合了iterator接口,可以使用for of 和 ... 扩展运算符进行遍历(三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构。

  1. 声明及方法
      let  S = new Set()  // 声明

      let arr = ['1', '2', '3', '2', '1'];
      let unrepeatedArr  = new Set(arr);  // 不改变原数组
      console.log(unrepeatedArr) 
      
      console.log(unrepeatedArr.size);  //set集合的长度,类似于length
 
      unrepeatedArr.add('5')  // 添加一个元素,添加重复得元素不生效
      console.log(unrepeatedArr);

      unrepeatedArr.delete('5')   //删除一个元素,删除里面没有的元素不报错
      console.log(unrepeatedArr);

      console.log(unrepeatedArr.has('2') );  //查找元素, 返回Boolean值

      unrepeatedArr.clear(unrepeatedArr) //清空元素
      console.log(unrepeatedArr);
  1. 实际应用
   求交集:
    let arr = ['1', '2', '3', '2', '1'];
    let ARR = ['1', 2, '4'];

    let mixArr = [...new Set(arr)].filter(item => {
      let ARRSet = new Set(ARR);
      if (ARRSet.has(item)) return true;
      else return false;
    })

    console.log(mixArr)  // 1
   
   并集: 方法太多了
   1. 用add
   2.先合并数组再去重
   
   差集: A里有B中没有的或反过来
   交集取反就好了

map结构

定义:ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了字符串—值的对应,Map 结构提供了值—值的对应,是一种更完善的 Hash 结构实现。也实现了iterator接口和...扩展。 注: 对象的结构 本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键。

const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false

属性:

  • size:返回字典所包含的元素个数

操作方法:

  • set(key, val): 向字典中添加新元素
  • get(key):通过键值查找特定的数值并返回
  • has(key):如果键存在字典中返回true,否则false
  • delete(key): 通过键值从字典中移除对应的数据
  • clear():将这个字典中的所有元素删除

遍历方法:

  • keys():将字典中包含的所有键名以数组形式返回
  • values():将字典中包含的所有数值以数组形式返回
  • forEach():遍历字典的所有成员

数值扩展方法

  1. Number.EPSILON:JavaScript表示的最小值,可用来提高精度,值为2.220446049250313e-16;
  2. 进制: 2进制:0b ; 8进制:0O ; 16进制:0x;
  3. Number.isFinite(num):检测一个数值是否为有限数,返回值为Boolean,是为true
  4. Number.isNAN(num):检测一个数值是否为NAN,ES5中是一个单独的函数,但现在放在number中,是为false
  5. Number.parseInt(num), Number.parseFloat(num):将字符串转化为数值型,如果字符串以字母开头将字符串转化为NAN。
  • parseInt将字符串转化为整数,但不会保留小数位,且不会有进位;
  • parseFloat将字符串保留为小数类型,只识别第一个小数点;
  1. Number.isInteger(num): 判断数值是否为整数,是为true,不识别字符串;
  2. Math.trunc(num): 将数字保留为整数,可以识别字符串;
  3. Math.sign(num): 判断一个数值是否为正数、 0 、 负数,可以识别字符串;正数返回值为1, 负数返回值为-1,0 返回值为0。

对象的扩展方法

  1. Object.is(obj1, obg2): 判断两个值是否完全相等,类似于===,但是在判断NAN是否等于NAN时,返回为true;
  2. Object.assign(obj1, obj2): 将后面的对象向前面的对象合并,
  • 如果对象只有一层为深拷贝,如果对象为多层为浅拷贝。
  • 会改变原被合并的对象obj1,,返回值为合并后的obj1;
  1. Object.setPrototypeOf(obj1,obj2),Object.getPrototypeOf(obj1):设置对象原型
  • tPrototypeOf是将obj2的值插入obj1的原型中;
  • getPrototypeOf得到的值为obj2的值;

模块化

优势: 防止命名冲突,代码复用,高维护性。

export暴露导出

1. 分别暴露:分别导出A和B,如果要导出必须在定义的时候导出,不能导出变量否则报错;
export let A = '1';
export let B = '2';

2. 统一暴露: 这样可以导出变量
export{
 A: A,
 B
}

3. 默认暴露
export default C;

import引入

1. *代表全部导入、 as取别名,demo为对象包含分别暴露的信息
import * as demo from './src/demo.js';

2.  多个暴露可以解构, 也可以用as取别名
import {A , B} from './src/demo.js';

3. 默认暴露的使用,需要 + defalut
import * as demo from './src/demo.js';
demo.defalut.C

4. 默认暴露解构的情况, demo就是默认导出的对象
import {defalut as demo} from './src/demo.js';
demo.C

5. 默认暴露简便形式,只针对默认暴露, demo就为对象
import demo from './src/demo.js';
demo.C

注: import引入和require引入 import demo from './src/demo.js' = const demo = require('./src/demo.js')

babel转换为es5

安装、转义、打包 image.png

ES7

方法扩展

  1. Arr.includes(元素): 检查数组中是否含有该元素,返回值为boolean;(indexof也能实现,但返回为下标)
  2. num1 ** num2: 指数操作,和Math.pow(num1,num2)一样;

ES8

async, await

  1. async 的返回值为promise对象,promise的状态及结果由函数的return值决定。
1. 返回值为字符串或其他
        async function fun(){
            return '任何一个值或空' 
        }
        console.log(fun())  // 返回一个成功状态的promise

2. 抛出一个错误   
        async function fun1(params) {
            throw new Error('我现在错误了')
        }
        console.log(fun1()); //返回一个错误的promise

3. 返回一个promise        
        async function fun2(params) {
            return new Promise((resolve, rejected) =>{
                resolve('我想成功')
            })
        }
        console.log(fun2());  // 返回一个成功的promsie
  1. await:在await右侧的表达式走完之前,js不向下走。 await必须放在async内; await右侧的表达式通常是promise对象; await返回的是promise成功的值; await的promise失败时,抛出错误,需0要用try{}catch{}接收;
        let p = new Promise((resolve, rejected) => {
            resolve('我输入的值')
        })

        async function fun() {
            let  result = await p;
            console.log(result)     // 值为我在resolve中输入的值
        
        }
        
    async function fun1(){
     try{
      let  result = await p;
            console.log(result) 
     }catch(err){
      console.log(err)
     }
    }

        fun()

对象方法的扩展

  1. Object.keys(obj), Object.values(obj): keys获取的是obj对象的键, values获取的是值,返回的是数组。
  2. Object.entries(obj):返回值为数组,并且每个数组的元素都是对象的键值对,这个键值对的格式也是数组,方便创建map结构。(二维数组)
  3. create, getOwnPropertyDescriptor
      const obj = Object.create(null, {    // 第一个参数为原型对象, 第二个为描述对相关
          name: {
              value: '用到的',
              writable:true,
              configurable:true,
              enumerable: true
          }
      })
       
      console.log(Object.getOwnPropertyDescriptor(obj))  //获取描述对象

ES9

对象扩展

  1. rest 见上面ES6部分,ES6只是针对于数组,现在也是支持对象。
  2. ...对象的扩展运算符,返回值为用‘ ,’分割的键值对,用法和上面数组的扩展一样;

正则扩展

  1. () , ?: 字符串的分组、 命名结果; 通过reg.exec(str)获取结果;
  2. 正向断言: 根据后面的值,判断前边的内容是不是合法的;
  3. 反向断言:根据前边的值,判断后面的内容是否是合法的;
  4. dotall: 匹配任意字符;

ES10

对象扩展

  1. Object.fromEntries(arr): 将二维数组转化为对象,为ES8中Object.entries(obj)的逆运算;(二维数组只转化2个元素,第一个元素当键名,第二个元素当键值,后面的不管)

字符串扩展

  1. str.trimStart(), str.trimEnd():清除字符串空格start为左侧,end为右侧,中间的不管;(trim方法全部清除,中间的也不管)

数组扩展

  1. arr.flat(2):将多维数组转化为低维数组,参数决定维数;
  2. arr.flatMap( () => {} ) : flat + map的结合; (map的返回值为操作的数组,包括在方法内对数组进行的操作)

symbol扩展

  1. Symbol.prototype.description(s): 获取symbol格式的s的原型描述

ES11

静态属性

  1. #: 静态属性简写

promise扩展

  1. promise.allSettled([P1, P2] ):调用并得到多个promise的返回值,返回值为一个成功的promise,这个promise的值为数组,每个元素为执行的promise的值,如果某个promise执行失败, promise.allSettled([P1, P2] )依旧会的到一个成功的promise,但是那个失败的promise的值变为抛出的错误。

字符串方法扩展

  1. str.matchAll():正则批量匹配的结果,数据的批量提取;

可选链操作符

?. : 避免无意义的报错。在做层层判断时,当一个值不传时,代码会报错,但是用 ?. 可选链式操作符,就会输出undefined

!. :TypeScript的语法,叫非空断言操作符(non-null assertion operator),和?.相反,这个符号表示对象后面的属性一定不是null或undefined。

拓展及应用

动态import加载

使用

        function fun(params) {
            import('./a.js').then( module => {          // 返回一个promise
                console.log(module)   //  其中包括文件a.js导出的对象
            })
        }
        fun()

BigInt 大整形,新的基础数据类型

  1. 定义声明: 在数据后 + n
      let n = 123n;          
      console.log(typeof(n));   // bigint
  1. BigInt方法: 将整数转换为bigint型,但不包括浮点型。
      let n = 123;
      console.log(BigInt(n));   // 将数字型转化为bigint型
  1. 用处: 大数值运算
js存在最大值Number.MAX_SAFE_INTEGER,在这个值之后不能再进行运算,但是BigInt型的数据可以继续运行;

globalThis: 全局this,始终指向全局的this