zoukankan      html  css  js  c++  java
  • ECMAScript新语法、特性总结

    前言

    从2015年的ES6开始,JavaScript的语言标准每年都在更新,其中尤其以ES6的力度之大,到现在ES10已经发布,这里总结一下新语法。

    参考:阮一峰 ECMAScript 6 教程 、ECMAScript 6入门 、1.5万字概括ES6全部特性

    声明变量

    • const   块级作用域,变量被const声明后不允许改变,通常在声明时定义
    • let  块级作用域

    注意点:

    变量提升:
    var存在变量提升,const、let不存在变量提升,意思是:var声明的变量在声明之前可以访问,访问到的值为undefined;const、let声明的变量在声明之前不可以访问,如果访问直接报错。
    暂时性死区:
    var tmp = 123;
    if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
    }
    看上面这段代码,if内的第一行会报错。ES6明确规定,如果区块中存在let和const命令,这个区块对这些命声明的变量,从一开始就形成了封闭的作用域。凡是在声明之前就是用这些变量,就会报错。在语法上称为“暂时性死区”

    解构赋值

    ES6中只能对数组进行解构赋值,ES7增加了对象解构赋值的支持(其他类型的不知什么时候支持的)

    字符串解构赋值
    let [ a, b, c ] = "hello"
    // a: "h", b: "e", c: "l"
    
    数组解构赋值
    let array= ["one", "two", "three", "four"];
    let [a, b, c] = array;    // 同时定义了三个变量,并按照顺序为其赋值
    
    对象解构赋值
    let array = { foo: "aaa", bar: "bbb" };
    let { foo, bar } = abc;    // 按照 键的名称 赋值给新的变量
    let { foo: oof } = abc;    // 将abc中foo的值拿出来,赋给新的变量oof
    let { foo, bar, def = "haha" } = abc; // 为变量def设置默认值
    
    函数参数解构赋值
    function func([ x = 0, y = 1 ]) {}
    function func({ x = 0, y = 1 }) {}

    运算符

    延展操作符

    延展操作是将数组/对象内的所有成员依次拿出来,如果所有成员是值类型,可以看做是深拷贝。

    // 数组
    let arr1 = [ 'a', 'b', 'c'];
    let arr2 = [ 1, 2, 3 ];
    let result = [ ...arr1, ...arr2 ]; 
    // 对象(注意:如果对象中的属性名相同,会被覆盖)
    let smallDog = { name:'小煤球', age: 1 };
    let bigDog = { name: 'Python', age: 2 };
    let dog = { ...smallDog, ...bigDog };

    求幂运算符

    ES7 新增,与 Math.pow() 作用相同

    const result = x ** 5

    可选链操作符

    ES2020 新增,当使用某些对象的时候,为了更安全地访问它们的属性,我们使用可选链操作符。

    obj.prop?.prop2

    在 ES2020 之前,我们通常通过三目运算符或、if 判断 或 && 运算符,现在我们可以使用语法更为简便的可选链操作符

    const street = user && user.address && user.address.street;
    const address = user ? user.address : null;
    
    const street = user?.address?.street;
    const address = user?.address;

    如果这个访问链中的某个值不存在,将不会继续访问下去,返回 undefined,否则将是我们期望访问的属性的值,再也不用看到  "Cannot read property 'xxx' of undefined" 这种 error 了!

    空位合并操作符

    ES2020 新增,由于 JavaScript 是动态类型的,在分配变量时常常需要对 真/假 值的处理,比如:

    let person = {
      profile: {
        name: "",
        age: 0
      }
    };
    console.log(person.profile.name || "Anonymous"); // Anonymous
    console.log(person.profile.age || 18); // 18
    
    console.log(person.profile.name ?? "Anonymous"); // ""
    console.log(person.profile.age ?? 18); // 0

    这时双管道符会将我们认为的有效值覆盖成默认值,这令人不爽。我们可以用 ?? 空位合并操作符来代替它,仅当值为 null 或 undefined 时才允许使用默认值。?? 与 ? 的区别是:前者是对有效值的严格处理,后者是对空缺值的友好处理。

    字符串扩展

    1.模板字符串

    let age = 20;
    let str = `我今年${age}岁了`;
    let str2 = `想要换行
    直接换就可以了
    无需添加那么多加号
    `;

    注意:1.必须是反引号``,不是单引号。 2.大括号内可以进行简单的数值运算(如加减乘除)、逻辑运算(与或非)、函数调用、三目运算。

    2.字符串遍历:for - of

    let str = "ES6不香吗?";
    for (let i of str) {
      console.log(i);  
    }

    3.标签模板

    标签模板是模板字符串与函数调用的结合,来看例子:

    let  name = '小白', age = 20;
    let message = myTag`我是${name},今年${age}岁了`; // message 最终内容是: "哈哈哈"
    
    function myTag(stringArr, value1, value2) {
        console.log(stringArr);  // ["我是", ",今年", "岁了", raw] 注意:该数组有一个raw属性,保存的是转义后的原字符串
        console.log(value1);     // 小白
        console.log(value2);     // 20
        return "哈哈哈";     // 需要有返回值
    }

    其实就是调用了字符串处理函数,返回处理后的字符串,这里要注意函数的传参:第一个参数是数组,存放着分割后的字符串片段;后面的参数是模板字符串中的变量。

    4.Unicode表示法

    大括号包含表示Unicode字符

    "u{20BB7}" // 吉
    "u{41}u{42}u{43}" // ABC

    5.codePointAt()、fromCodePoint()

    在JavaScript内部,字符以UTF-16的形式存储,每个字符固定为2个字节,对于那些需要4个字节存储的字符并不支持,ES6中使用 codePointAt() 方法来存储四字节的字符。

    let s = '猿';
    console.log(s.codePointAt(0)); // 29503
    console.log(String.fromCodePoint(29503)); // 猿

    6.其它新增方法:

    repeat()        把字符串重复n次,返回新字符串
    macthAll()     返回正则表达式在字符串的所有匹配
    includes()      检查字符串中是否存在指定的字符(子字符串),返回布尔值
    startsWith()   字符串头部是否以 ... 开头
    endsWith()     字符串尾部是否以 ... 开头
    padStart() / padEnd()  头部补全/尾部补全
        "ab".padStart(5,"dc") 接收两个参数,第一个指定字符串最小长度,第二个用来补全长度的字符串,默认使用空格补全

    数字类型的扩展

    Number.MAX_SAFE_INTEGER 最大安全数值 和 Number.MIN_SAFE_INTEGER 最小安全数值:

    MAX_SAFE_INTEGER 是一个值为 9007199254740991的常量,因为 JavaScript 的 number 类型使用了双精度浮点数数据类型,这一数据类型能够安全存储 -(2^53 - 1) 到 2^53 - 1 之间的数值(包含边界值)

    二进制表示法:        0b或0B开头表示二进制(0bXX或0BXX)
    八进制表示法:        0o或0O开头表示二进制(0oXX或0OXX)
     Number.EPSILON:        数值最小精度
     Number.MIN_SAFE_INTEGER:最小安全数值(-2^53)
     Number.MAX_SAFE_INTEGER:最大安全数值(2^53)
     Number.parseInt():        返回转换值的整数部分
     Number.parseFloat():    返回转换值的浮点数部分
     Number.isFinite():        是否为有限数值
     Number.isNaN():        是否为NaN
     Number.isInteger():    是否为整数
     Number.isSafeInteger():是否在数值安全范围内
     Math.trunc():        返回数值整数部分
     Math.sign():        返回数值类型(正数1、负数-1、零0)
     Math.cbrt():        返回数值立方根
     Math.clz32():        返回数值的32位无符号整数形式
     Math.imul():        返回两个数值相乘
     Math.fround():    返回数值的32位单精度浮点数形式
     Math.hypot():    返回所有数值平方和的平方根
     Math.expm1():    返回e^n - 1
     Math.log1p():    返回1 + n的自然对数(Math.log(1 + n))
     Math.log10():    返回以10为底的n的对数
     Math.log2():    返回以2为底的n的对数
     Math.sinh():    返回n的双曲正弦
     Math.cosh():    返回n的双曲余弦
     Math.tanh():    返回n的双曲正切
     Math.asinh():    返回n的反双曲正弦
     Math.acosh():    返回n的反双曲余弦
     Math.atanh():    返回n的反双曲正切

    BinInt 任意精度整数

    JavaScript 第7个原始类型(ES2020),是个任意精度的整数。变量可以表示超过 MAX_SAFE_INTEGER 的数字,并且不失精度。

    数组的扩展

    1.扩展方法

     Array.from():将类数组、可遍历对象转化为真正的数组。
        类数组对象:包含length的对象、Arguments对象、NodeList对象
        可遍历对象:String、Set结构、Map结构、Generator函数
     Array.of():     转换一组值为真正数组,返回新数组
     includes():  判断数组中是否有某成员
     copyWithin():把指定位置的成员复制到其他位置,返回原数组
     find():           返回第一个符合条件的成员
     findIndex():   返回第一个符合条件的成员索引值
     fill():             根据指定值填充整个数组,返回原数组
     keys():          返回以索引值为遍历器的对象
     values():       返回以属性值为遍历器的对象
     entries():      返回以索引值和属性值为遍历器的对象
     数组空位:       ES6明确将数组空位转为undefined

    2.扩展应用

    克隆数组:const arr = [...arr1]
    合并数组:const arr = [...arr1, ...arr2]
    拼接数组:arr.push(...arr1)
    代替apply:Math.max.apply(null, [x, y]) => Math.max(...[x, y])
    转换字符串为数组:[..."hello"]
    转换类数组对象为数组:[...Arguments, ...NodeList]
    转换可遍历对象为数组:[...String, ...Set, ...Map, ...Generator]
    与数组解构赋值结合:const [x, ...rest/spread] = [1, 2, 3]
    计算Unicode字符长度:Array.from("hello").length => [..."hello"].length

    函数扩展

    1.箭头函数

    () => {} 与function关键字声明的函数相比,除了语法上的简洁,this的指向也不同。箭头函数与包围它的代码共享一个this,因为其内部根本没有this。

    // 只有一个参数时,括号可以省略
    (a) => { console.log(a) }   可以简写为:  a => { console.log(a) }
    // 有返回值时,花括号和return可以省略
    (a) => { return a }   可以简写为:  a => a
    // 返回值为键值对时,外面是圆括号,里面是花括号
    (a) => { return { a:"a", b:"b" } }   可以简写为:  a => ({a:"a",b:"b"})

    箭头函数注意事项:

    函数体内的this是定义时所在的对象而不是使用时所在的对象
    不能修改this
    不可当作构造函数,因此箭头函数不可使用new命令
    不可使用yield命令,因此箭头函数不能用作Generator函数
    不可使用Arguments对象,此对象在函数体内不存在(可用rest/spread参数代替)

    2.函数参数

    默认参数:
    function ( a = 1, b = "hello" ) {}
    function ( a, b = getValue() ) {}
    
    剩余参数:
    let arg1 = "宋小宝", arg2 = "赵薇", arg3 = "王菲", arg4 = "那英";
    let logName = ( arg1, ...arg2 ) => {
        console.log(arg1, arg2);
    }
    logName(arg1, arg2, arg3, arg4)  // 宋小宝 ["赵薇", "王菲", "那英"]
    
    延展参数:
    延展参数其实就是在函数调用时,利用延展操作符
    myFunc( a, ...b ); // 一次性传了很多参数

    3.函数的name属性

    返回函数的名称

    // 将匿名函数赋值给变量:空字符串(ES5)、变量名(ES6)
    const a = () => {};
    const b = function(){};
    console.log( a.name, b.name );  // 谷歌浏览器上测试(支持ES6语法):"a" "b" ;IE11测试(只支持ES5):undefined
    
    // 将具名函数赋值给变量:函数名(ES5和ES6)
    function myFunc(){}
    const a = myFunc;
    console.log( myFunc.name, a.name );  //  "myFunc"  "myFunc"
    
    // bind返回的函数:bound 函数名(ES5和ES6)
    ... 不不举例
    
    // Function构造函数返回的函数实例:anonymous(ES5和ES6)
    ... 不举例

    4.尾调用优化

    5.块级函数

    在代码块中能够声明函数,函数也被称之为块级函数,在严格模式下,块级函数会提升到当前所处代码块的顶部,在整个代码块中能够被访问,在代码块之外的地方就不能被访问。在非严格模式下,块级函数会被提升到全局作用域。

    正则扩展

    1.构造函数的参数使用规则变更

    2.正则方法调用变更

    字符串对象的 match() 、replace() 、search() 、split()均可使用正则表达式,在语言内部调用都调用RegExp的实例方法,从而做到所有与正则相关的操作,全部定义在RegExp对象上

    String.prototype.match 调用 RegExp.prototype[Symbol.match]
    String.prototype.replace 调用 RegExp.prototype[Symbol.replace]
    String.prototype.search 调用 RegExp.prototype[Symbol.search]
    String.prototype.split 调用 RegExp.prototype[Symbol.split]

    3.其它

    u 修饰符
    y 修饰符
    s 修饰符
    sticky 属性
    flags 属性
    后行断言
    Unicode 属性类

    对象的扩展

    详情见 谈论JavaScript对象——个人总结

    新增数据类型

    1.Symbol

    指的是独一无二的值。

    const set = Symbol(str) // 创建一个独一无二的值,参数可选
    // 原型方法:
    Symbol():创建以参数作为描述的Symbol值(不登记在全局环境)
    Symbol.for():创建以参数作为描述的Symbol值,如存在此参数则返回原有的Symbol值(先搜索后创建,登记在全局环境)
    Symbol.keyFor():返回已登记的Symbol值的描述(只能返回Symbol.for()的key)
    Object.getOwnPropertySymbols():返回对象中所有用作属性名的Symbol值的数组
    
    // 实例方法:
    Symbol.hasInstance:指向一个内部方法,当其他对象使用instanceof运算符判断是否为此对象的实例时会调用此方法
    Symbol.isConcatSpreadable:指向一个布尔值,定义对象用于Array.prototype.concat()时是否可展开
    Symbol.species:指向一个构造函数,当实例对象使用自身构造函数时会调用指定的构造函数
    Symbol.match:指向一个函数,当实例对象被String.prototype.match()调用时会重新定义match()的行为
    Symbol.replace:指向一个函数,当实例对象被String.prototype.replace()调用时会重新定义replace()的行为
    Symbol.search:指向一个函数,当实例对象被String.prototype.search()调用时会重新定义search()的行为
    Symbol.split:指向一个函数,当实例对象被String.prototype.split()调用时会重新定义split()的行为
    Symbol.iterator:指向一个默认遍历器方法,当实例对象执行for-of时会调用指定的默认遍历器
    Symbol.toPrimitive:指向一个函数,当实例对象被转为原始类型的值时会返回此对象对应的原始类型值
    Symbol.toStringTag:指向一个函数,当实例对象被Object.prototype.toString()调用时其返回值会出现在toString()返回的字符串之中表示对象的类型
    Symbol.unscopables:指向一个对象,指定使用with时哪些属性会被with环境排除

    应用场景:

    唯一化对象属性名:使用 symbol 可以保证不会与其他属性名产生冲突

    遍历属性名:无法通过for - in, for - of, Object.keys()等返回,只能通过 Object.getOwnPropertySymbols() 返回

    2.Set

    Set

    集合,每个成员都唯一且没有重复的值,是一个无序的数据集合。

    cosnt set = new Set(array); // 声明一个set变量
    属性:size,相当于数组的 length
    方法:
    add():添加值,返回实例
    delete():删除值,返回布尔值
    has():检查值,返回布尔值
    clear():清除所有成员
    keys():返回以属性值为遍历器的对象
    values():返回以属性值为遍历器的对象
    entries():返回以属性值和属性值为遍历器的对象
    forEach():使用回调函数遍历每个成员

    应用:

    字符串去重:[...new Set(str)],join("")
    数组去重:[...new Set(arr)]  或  Array.from(new Set(arr))

    注意:

    遍历顺序:插入顺序
    添加相同对象时,会认为是不同的对象

    WeakSet

    和Set结构类似,与Set的不同在于:(1) 成员值只能是对象,确切地说是只能存放对象引用,不能存放值类型 (2) WeakSet中存放的值都是弱引用的,即WeakSet通过弱引用存储元素。如果没有其他对象引用该对象,则会从WeakSet中清除该对象。因此,你不能遍历WeakSet对象,也不能获取它的大小。

    const a = new WeakSet(arr);
    方法:
    add():添加值,返回实例
    delete():删除值,返回布尔值
    has():检查值,返回布尔值

    应用场景:

    临时存放一组对象或存放跟对象绑定的信息:只要这些对象的引用在外部消失,它在WeakSet结构中的引用就会自动消失,完全不会影响垃圾回收。例如:
    储存DOM节点。DOM节点被移除时自动释放此成员,不用担心这些节点从文档移除时会引发内存泄漏

    3.Map

    Map

    类似于Object的数据结构,区别是:object的键只能是字符串或数字,map的键可以是任何类型的值。

    const map = new Map(); // 创建Map实例
    属性:size 返回成员总数
    方法:
    get():返回键值对
    set():添加键值对,返回实例
    delete():删除键值对,返回布尔值
    has():检查键值对,返回布尔值
    clear():清除所有成员
    keys():返回以键为遍历器的对象
    values():返回以值为遍历器的对象
    entries():返回以键和值为遍历器的对象
    forEach():使用回调函数遍历每个成员

    注意:

    遍历顺序:插入顺序
    键跟内存地址绑定,只要内存地址不一样就视为两个键
    Object结构提供 字符串/数字 —— 值 的对应,Map结构提供 值 —— 值 的对应

    WeakMap

    与Map结构类似,不同在于:(1) 成员的键只能是对象,值可以是任意的 (2) 键是弱引用的,因此键不可枚举,导致整个结构不可枚举。

    get():返回键值对
    set():添加键值对,返回实例
    delete():删除键值对,返回布尔值
    has():检查键值对,返回布尔值

    与WeakSet一样,不影响垃圾回收机制。

    Class

    终于,JavaScript有那么一点像传统的面向对象语言了,与Java类的使用方法甚是相似。class关键字很早就存在于JavaScript中,但一直没真正使用,直到ES6。需要着重强调的是:js中的class并不是类,class关键字的使用并不改变JavaScript基于原型这一本质,它只是构造函数的语法糖,可以看做是构造函数的另一写法。

    ES6的class绝大部分功能,都可以通过ES5来实现,class写法能够让对象原型的写法更加清晰、更像面向对象变成的语法。类内的所有方法都定义在prototype属性上面,在类的实例上调用方法,实际上就是调用原型(链)上的方法。

    1.constructor方法

    构造方法,通过new操作符生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,会默认添加一个空的constructor方法。

    该方法会默认返回实例对象(即this),当然你可以完全返回另外一个对象,如果是这样,产生的实例将完全不是class定义的类的实例。

    2.getter和setter,取值函数和存值函数

    我们可以在类的内部使用 get 和 set 关键字,为某个属性设置拦截器,拦截该属性的存取行为。

    class MyClass {
      get hello() {
        return 'getter'; // get函数一定要有返回值
      }
      set hello(value) {  // set函数有参数
        console.log('setter: '+value);
      }
    }

    在这里,hello属性的取值和存值的行为都被自定义了。set和get函数是设置在 Descriptor 对象上的。

    let descriptor = Object.getOwnPropertyDescriptor(MyClass.prototype, "hello");
    "get" in descriptor  // true
    "set" in descriptor  // true

    3.属性表达式

    类的属性名(方法名),可以采用表达式

    let methodName = 'getArea';
    
    class Square {
      constructor(props) {
        super(props);
      }
    
      [methodName]() {
        // ...
      }
    }

    4.class表达式

    const MyClass = class Me {
      getClassName() {
        return Me.name;
      }
    };

    你可能以为上面这段代码没什么,不过是定义了一个类Me,然后为其增加了一个引用,名为MyClass,实则不然。

    这个类的名字为Me不假,但是Me只能在类的内部使用,指代当前类。在外部,只能通过MyClass引用。

    // 如果类的内部没有用到Me,可以将其省略,类似于匿名函数。
    const MyClass = class { /* ... */ };
    // 也可以写出立即执行的class,即只生成一个实例
    let person = new class {
      constructor(name) {
        this.name = name;
      }
      sayName() {
        console.log(this.name);
      }
    }('张三');

    5.静态方法

    通过static关键字修饰的方法都是静态方法。该方法不会被实例继承,而是直接通过类来调用。父类的静态方法可以被子类继承,静态方法也可以从super对象上调用。

    如果静态方法内出现 this ,这个 this 指的是类,不是实例。

    6.静态属性

    静态属性指的是Class本身的属性,即Class.propName,不是定义在实例对象上的属性,也是被 static 关键字修饰的。

    class Foo {
      static hello = "a";
    }
    Foo.hello2 = 1;

    7.继承

    extends关键字实现继承。需要说明的是,子类的构造函数内一般要使用super关键字,当做方法调用,代表父类的构造函数。另外,super()只能用在子类的构造函数中,用在其他地方就会报错。

    注意点:

    1.严格模式。类和模块内部,默认就是严格模式,所以不需要'use strict'
    2.不存在变量提升。使用在前,定义在后这样的行为,会报错。
    3.name属性。本质上,ES6类是对ES5构造函数的一层封装,因此函数许多特性被Class继承,包括name属性
    4.Generator方法。在某个方法前面加上 * 号,就表示该方法是一个 Generator 函数
    5.async方法,在方法名前面加上async关键字。
    5.this的指向。默认指向类的实例,但是如果单数使用该方法,很可能报错。
    class Logger {
      printName(name = 'there') {
        this.print(`Hello ${name}`);
      }
    
      print(text) {
        console.log(text);
      }
    }
    
    const logger = new Logger();
    const { printName } = logger;
    printName(); // TypeError: Cannot read property 'print' of undefined
    解决办法是使用箭头函数,或者在构造函数中使用 bind(this)

    8.类的私有成员(ES2020)

    在变量名前加一个 # 号表示私有成员,只可以在类/实例内部访问。

    class Message {
      #message = "Howdy"
       message = "hello"
    
      greet() { console.log(this.#message) }
    }
    
    const greeting = new Message()
    
    greeting.greet() // Howdy
    greeting.message // hello
    greeting.#message // Private field '#message' must be declared in an enclosing class

    Module模块化

    import

    import { firstName, lastName } from './abc.js';  // 按需引入,逐一加载
    import { firstName as name } from './abc.js';  // 将引入的变量重命名
    import * as API from './api.js';   // 模块整体加载,命名为API,通过API.xxx使用。
    import abc from 'def.js';  // 默认导入,当def.js文件中有export default默认导出时才可以。此时的导入名称 abc 可以任意拟定
    import 'lodash';  // 全局引入

    注意:

    1.import命令引入的变量都是只读的,不能修改,我们也应该将其当成完全只读。

    import { a } from './xxx.js'
    a = {}; // Syntax Error : 'a' is read-only; 不能修改
    a.foo = "hello"; // 允许改写a的属性,但不建议这样做

    2.import命令具有提升效果

    foo();
    import { foo } from 'my_module';

    是因为import的执行早于foo的调用。这种行为的本质是,import命令时编译阶段执行的,在代码运行之前。

    3.import是静态执行,不能使用表达式和变量

    // 报错
    import { 'f' + 'oo' } from 'my_module';
    
    // 报错
    let module = 'my_module';
    import { foo } from module;
    
    // 报错
    if (x === 1) {
      import { foo } from 'module1';
    } else {
      import { foo } from 'module2';
    }

    export

    export const firstName = "Jim";
    export { firstName, lastName, year };
    export { firstName as name };  // 导出时重命名
    export default firstName;  // 默认导出
    
    // 错误的写法:
    export 1;
    var a = 1;
    export a;
    // 正确的写法:
    export var a = 1;
    export {a};
    export {b as a};

    复合写法

    export { foo, bar } from 'my_module';  // 导入的同时导出,在这里做转发
    export { foo as myFoo } from 'abc';    // 改名之后导出
    export * from 'my_module';   // 整体输出
    export { default } from 'foo';  // 默认导出,做转发
    export { abc as default } from "./someModule";  // 具名导出改为默认导出
    export { default as abc } from './someModule';  // 默认导出改为具名导出
    
    export * as Utils from './utils.js';    // ES2020 新增,以前不可以这样做
    它等同于:
    import * as utils from './utils.js'
    export { utils }

    动态导入 Dynamic import

    有时候一个页面用到的依赖不多,我们没必要将所有的依赖全都加载在浏览器中,而是需要的时候再加载,可以使用动态 import(即没用到的依赖代码,根本不会被发送到浏览器端,需要用到的时候再通过网络请求获取)。动态导入在 ES2020 正式进入语法标准,在此之前我们需要安装插件/依赖库才能使用。上面的 import/export 与它不同的是,前者是静态编译期执行,在代码执行之前就已经确定,而后者是在程序运行中动态获取,会发送按需请求的代码,不会增加额外的开销。

    if  (hello) {
        const module = await import('./dynamicmodule.js');
        module.addNumbers(3, 4, 5);
    }

    Promise、Generator、Async/await

    详情看文章:JavaScript异步

    Proxy

    详情参考 谈论JavaScript对象——个人总结

    Reflect

    详情参考 谈论JavaScript对象——个人总结

    globalThis

    JavaScript可以运行在多个环境中:浏览器、NodeJS、Web Worker。他们各自的全局对象也有所不同,例如浏览器中是 window,NodeJS中是 global,Web Worker中是 self。如果有更多的环境,全局对象也将有所不同,所以在 ES2020 之前我们不得不自己实现检测环境,然后使用正确的全局对象。ES2020 的 globalThis 始终引用全局对象:

    globalThis.setTimeout === window.setTimeout // true

    .

  • 相关阅读:
    jquery 的ready() 与window.onload()的区别
    使IE6同样支持圆角效果
    菜鸟级三层框架(EF+MVC)项目实战之 系列一 EF零基础创建领域模型
    asp.net webform 与mvc 共享session
    用户密码安全存储解决方案
    vs2010 web负载测试解决提示:结果存储类型为“Database”,但尚未指定结果储存库连接字符串。
    菜鸟级三层框架(EF+MVC)项目实战之 系列二 对数据访问层的抽象中
    菜鸟级三层框架(EF+MVC)项目实战之 系列四 UI层ASP.NET MVC实现CRUD
    菜鸟级三层框架(EF+MVC)项目实战之 系列二 对数据访问层的抽象下
    WP7之文件传送利器(web service)
  • 原文地址:https://www.cnblogs.com/V587Chinese/p/12040412.html
Copyright © 2011-2022 走看看