只例举 EcmaScript 的变化,不说细节
建议经常看看 EcmaScript 的改变以及提案,很多语法都在像 Linux Shell 等靠齐,相信 JavaScript(EcmaScript)会越来越强大,当然,TypeScript 作为 JavaScript 的语法糖,也是一样的。。

EcmaScript 6

  • 1.let && const

    用于声明变量,只在当前代码块内生效,const 相比于 let,const 声明常量,对于引用类型,不限制其改变,两者都不存在变量提升

    for (let i = 0; i < 10; i++) {
    }
    console.log(i);
    // ReferenceError: i is not defined
    
    const a=0;
    a=1;  //Uncaught TypeError: Assignment to constant variable.
    
  • 2.解构赋值

    提取数组和对象里的值,对变量进行赋值,这里的数组包括下面要说的 Set 等,但是不包括 Map

    let [a, b, c] = [1, 2, 3];   // a:1 b:2 c:3
    let {name}={name:'duanxl'}   // name:duanxl
    let {foo} = {foo: 'baz'}; // foo:baz
    
  • 3.字符串扩展

    比如对字符串增加了迭代器(Itertor),模板字符串等等

    const domain='duanxl';
    const com=`https://${domain}.cn`
    
    let str='duanxl';
    for(let i of str){
        // ...
    }
    
  • 4.字符串新增方法

    • String.fromCodePoint() 相比于之前 Es5 的 fromCodePoint 方法,可以识别大于0xFFFF的码点
    • 增加String.raw(),返回一个可以转义斜杠(/)的字符串,通常可以用于模板字符串转义(即斜杠前面再加一个斜杠)
    • 增加String.normalize(),强调语言重音符号
    • 增加String.includes(),可以替代之前的 indexof(),返回 Boolean
    • 增加String.startsWith(),String.endsWith(),表示字符串是否在起始位置,返回 Boolean
    • 增加String.repeat(),将字符串重复 n 次
    • 增加String.replaceAll(),相比于之前的 String.replace(),可以进行全局替换,之前的 String.replace()不写全局匹配,只能匹配到第一项
  • 5.针对于正则扩展

    这里就不例举了。。。

  • 6.数字的扩展

    • Number.isFinite(),判断一个数值是否是有限的
    • Number.isNaN(),判断数值是否是 NaN
    • Number.parseInt(), Number.parseFloat(),之前就有,只是此次将两个方法移植到 Number 对象上,减少全局性的方法
    • Number.isInteger(),判断一个数值是整数
    • Number.EPSILON,表示最小浮点数间的误差,利用该方法,可以自行设置表示的最小精度,以解决之前的 0.1+0.2!==0.3 的问题
    • Math.trunc(),用于取出数值的小数部分
    • Math.sign(),判断数值是正数、负数、还是零
    • Math.cbrt(),计算数值的立方根
    • Math.clz32(),将参数转为 32 位无符号整数的形式,返回前导 0 数量
    • Math.imul(),返回两数相乘结果
    • Math.fround(),返回一个数的 32 位精度浮点
    • Math.hypot(),返回所有参数的平方和的平方根
  • 7.箭头函数

    // 普通函数
    var func=function(){};
    // 箭头函数
    const func=()=>{};
    // rest表达式
    cosnt func=(...args)=>{console.log(args)}
    

    注意点:

    • 1.箭头函数的作用域与之前的 function 作用域不同,箭头函数的作用域是定义时所在的对象,而不是像 function 一样,在调用时才决定
    • 2.不能当做构造函数,即不能使用 new
    • 3.不可以使用 arguments,可以使用上面的 rest 表达式
    • 4.不可以用作 Generator 函数
  • 8.数组的扩展

    • 1.Array.from(),将类数组对象转换为数组
    • 2.Array.of(),将参数值转换为数组
    • 3.Array.prototype.copyWithin(),将指定位置的成员复制到其他位置,会修改原数组
    • 4.Array.prototype.find(),查找符合条件的数组成员,返回该成员或者 undefined
    • 5.Array.prototype.findIndex(),返回符合条件的成员下标
    • 6.Array.prototype.fill(),数组填充
    • 7.Array.prototype.includes(),与上面字符串的 includes()一样,只是也挂载到了 Array.prototype 上
  • 9.对象的新增方法

    • 1.Object.is(),比较两个值是否相等,解决了 NaN!==NaN 的问题,当然,也会寻址
    • 2.Object.assign(),合并对象,可以轻松浅拷贝
    • 3.Object.getOwnPropertyDescriptors(),返回某个对象属性的描述对象(descriptor<{value,writable,enumerable,configurable}>)
    • 4.Object.setPrototypeOf(),设置对象原型(proto
    • 5.Object.keys(),Object.values(),Object.entries(),与上面数组的三个方法一致
  • 10.Symbol

    新增基本数据类型 undefined,number,string,null,boolean,bigInt,Symbol,目前 7 种,bigInt 在 Es9 中。。。
    表示唯一存在的数据,可以消除魔术变量名等

    • Symbol.for(),判断当前描述的 Symbol 是否存在,存在即复用,否则新建 Symbol
    • Symbol.keyFor(),返回 Symbol 的描述
  • 11.Set

    类似数组,成员唯一不重复的 Set 对象

    • Set.prototype.constructor,构造函数,默认 Set
    • Set.prototype.size 返回 Set 实例的长度
    • Set.prototype.add(value),添加
    • Set.prototype.delete(value),删除
    • Set.prototype.has(value),查找,返回 Boolean
    • Set.prototype.clear(),清空所有成员
    • WeakSet:与 Set 相似,WeakSet 的成员只能是对象,WeakSet 中的对象都是弱引用,如果没有其他引用,会立即回收

  • 12.Map

    键值对的集合(Hash) 结构,只能使用字符串作为 key,与上面的 Set 属性方法差不多,也存在 WeakMap

  • 13.Proxy

    代理目标对象,属于元编程

    • get: 拦截对象属性的读取
    • set: 拦截对象属性值的设置
    • apply: 拦截对象方法被调用
    • has: 拦截 for in 操作,返回 boolean
    • deleteProperty: 拦截删除属性的操作
    • ownKeys: 拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in 循环
    • getOwnPropertyDescriptor: 拦截 Object.getOwnPropertyDescriptor(proxy, propKey)读取
    • construct: 拦截构造函数被调用
    • …………….
  • 14.Reflect

    与 Proxy 相辅相成,属于元编程,一个代理,一个反射,将明显属于语言内部的方法放到 Reflect 上,看提案,以后会完善

  • 15.Promise

    异步编程的解决方案 只有三种状态:pending,fulfilled,rejected

    • Promise.prototype.then(),当状态改变时执行,即不为 pending,then 的顺序也对应不同的状态的回调
    • Promise.prototype.catch() 错误回调
    • Promise.all() 接收一个 Promise 的数组,包装成一个新的 Promise,且内部所有的Promise 状态为 resolved,状态才为 resolved
    • Promise.race() 接收一个 Promise 的数组,包装成一个新的 Promise,且内部只要有一个Promise 状态为 resolved,状态即为 resolved
    • Promise.allSettled() Es11 新增的,现在这里说了吧,不然目录看着不爽,接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是 fulfilled 还是 rejected,包装实例才会结束。即所有 Promise 回调执行后即结束
    • Promise.any() Es11 新增,和 race 反了一下,只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态
    • Promise.resolve(),将对象转为 Promise 对象,且返回状态 fulfilled
    • Promise.reject(), 将对象转为 Promise 对象,且返回状态 rejected
    • Promise.try(),同步方法同步执行,异步方法异步执行,缺点:同步方法会放到同步队列末尾执行
  • 16.Itertor

    遍历器,属元编程
    看了眼提案,之后还会完善 Itertor,实现其异步遍历

    • 目的,为所有数据结构提供一种访问机制,即 for … of 循环
    • 默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性上
    • 只要具有 Symbol.iterator 属性,就可以认为是“可遍历的”
    //为对象添加Itertor
    let obj = {
    data: [ 'hello', 'world' ],
    [Symbol.iterator]() {
    const self = this;
    let index = 0;
    return {
    next() {
    if (index < self.data.length) {
    return {
    value: self.data[index++],
    done: false
    };
    } else {
    return { value: undefined, done: true };
    }
    }
    };
    }
    };
    // 因为数组,字符串等默认就有Itertor,可以直接调用
    let arr = ['a', 'b', 'c'];
    let iter = arr[Symbol.iterator]();
    iter.next() // { value: 'a', done: false }
    iter.next() // { value: 'b', done: false }
    iter.next() // { value: 'c', done: false }
    iter.next() // { value: undefined, done: true }
    
    • 一般,使用 rest 表达式会调用 Itertor,还有解构,还有 Generator 函数也会调用

  • 17.Generator

    异步编程的解决方案,相当于一个状态机,内部状态有序操控,是对协程的实现

    // 实例
    function* helloWorldGenerator() {
        yield 'hello';
        yield 'world';
        return 'ending';
    }
    var hw = helloWorldGenerator();
    hw.next()
    // { value: 'hello', done: false }
    
    hw.next()
    // { value: 'world', done: false }
    
    hw.next()
    // { value: 'ending', done: true }
    
    hw.next()
    // { value: undefined, done: true }
    
    • yield,暂停后面的操作,并将紧跟 yield 够的值作为函数的返回对象
    • 数据结构与上面的 Itertor 相似,因此上面的 Itertor 的代码可以改造如下
    • nest(),顺序带入 yield 返回值执行函数
    • Generator.prototype.throw(),捕获错误
    • Generator.prototype.return(),结束遍历器
    • yield*,后面紧跟 Generator 函数,暂停当前 Generator,执行下一个 Generator
      //为对象添加Itertor
      let obj = {}
      myIterable[Symbol.iterator] = function* () {
          yield 'hello';
          yield 'world';
      };
    
  • 18.async

    • 其实就是 Generator 的语法糖,将 Generator 的* 替换成了 async,yield 替换成了 await
    • async 加装的函数返回一个 Promise 对象
      // 实现原理,其实就是将Generator加装在一个函数体内
      // 当然,这个函数不能执行,因为我用了关键字。。。
      function async(args) {
        return spawn(function* () {
            // ...
        });
      }
      
  • 19.ArrayBuffer

    数组二进制缓冲区

  • 20.class

    这里就不说了,之前的原型链继承

  • 21.module

    引入 module 语法, import,export,export default 等等

EcmaScript 7

    1. Array.prototype.includes() 上面 Es6 说到了
    1. 增加幂运算 **
    1. Math.pow(),指数运算

EcmaScript 8

  • 1.async/await 上面提到
  • 2.将 values(),keys(),entries()挂载到多个数据类型上,上面也有
  • 3.SharedArrayBuffer,对象用来表示一个通用的,固定长度的原始二进制数据缓冲区
  • 4.新增 Atomic 对象,用于操作 Buffer

EcmaScript 9

  • 1.改进 async/await,支持循环执行异步操作
    // 改进后
    async function process(array) {
        for await (let i of array) {
            doSomething(i);
        }
    }
    
  • 2.新增 Promise.prototype.finally() 不管状态如何,都会执行的回调

其他改变就不例举了,比如正则的捕获等

EcmaScript 10

  • 1.Array.prototype.flat(),数组铺平,不改变原数组,返回新数组
  • 2.Array.prototype.flatMap(),相比如 flat 方法,其实在数组铺平过程中,多执行一层 Array.prototype.map(),但是只能遍历展开一层
  • 3.增加String.prototype.trimStart(),String.prototype.trimEnd(),消除字符串首尾的空格,不会修改原字符串,返回清除空格后的字符串
  • 4.新增 Object.fromEntries(),将数组转换为对象,其实就是 Es6 中的反向 from
  • 5.增加String.prototype.matchAll(),正则全局匹配字符串
  • 6.新增基础数据类型 bigInt

    不知道有啥用,我太菜了。。

EcmaScript 11

  • Dynamic import

      if(...) {
          const menu = import('...');
      }
    
  • globalThis

    在 Web Worker 或者 iframe 中,只有 self 可以取到全局对象,而在 node 中,只能使用 global,globalThis 解决了这个问题,作为顶层对象

  • 有效变量判断符 ??,相比于||,??会判断左侧的的值是否为null或者undefined,如果左侧是 0,不会像||那样直接选择右侧的值

  • 可选链 ?.

  • Promise.any(),和 race 反了一下,只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态

  • Promise.allSettled(),接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是 fulfilled 还是 rejected,包装实例才会结束。即所有 Promise 回调执行后即结束

0