ES6-ES12新特性你都掌握了吗?

189 阅读12分钟

ES6-ES12

ES6新特性

1.let变量

2.const常量

3.变量的解构赋值【数组解构赋值和对象解构赋值

4.模板字符串

5.对象的简写

const school = {
    name,
    change,
    improve() {
        console.log('llllllaallalal');
    }
}

6.箭头函数

7.rest参数

8.扩展运算符(数组)

9.Symbol

10.迭代器

11.生成器函数

12.Promise

13.集合Set

14.字典Map

15.class类

16.Number的扩展

1.Number.EPSILONJavaScript 表示的最小精度

// EPSILON属性的值接近于 2.220446049250313e-16
// function equal(a, b) {
//     if (Math.abs(a-b) < Number.EPSILON) {
//         return true
//     } else {
//         return false
//     }
// }
// console.log(Number.EPSILON);
// console.log(0.1+0.2===0.3); // false
// console.log(equal(0.1+0.2, 0.3)); // true

// 2.二进制和八进制

let b = 0b1010; // 二进制 2**3 + 2**1 = 10
// console.log(b);
// console.log(3**3); // 3**3标识3的三次方
let o = 0o777; // 八进制 7*(8**2) + 7*(8**1) + 7*(8**0) = 511
// console.log(o);
let d = 100 // 十进制 100
let x = 0xff; // 15*16**1+15*16**0 = 255
// console.log(x);

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

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

// console.log(Number.parseInt('aaa134134love')) // NaN
// console.log(Number.parseFloat('ooo3.1415926神级')) // NaN

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

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

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

17.对象方法Object的扩展

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

        // 2.Object.assign 对象的合并
        // const obj1 = {
        //     name: 'M',
        //     age: 19
        // }
        // const obj2 = {
        //     name: 'T'
        // }
        // console.log(Object.assign({}, obj1, obj2)); //{ name: 'T', age: 19 }

        // 3.Object.setPrototypeOf    Object.getPrototypeOf
        const school = {
            name: '加大'
        }

        const cities = {
            xiaoqu: ['俄罗斯', '美国']
        }

        Object.setPrototypeOf(school, cities) // 将cities设置成为 school的原型
        console.log(Object.getPrototypeOf(school)); // 获取school的原型对象内容
        console.log(school);

18.浏览器使用ES6模块化引入

<script type="module">
        /* 
            在浏览器中也可以使用JavaScript modules(模块功能)了。目前支持这一特性的浏览器包括:
            Safari 10.1.
            谷歌浏览器(Canary 60) – 需要在chrome:flags里开启”实验性网络平台功能(Experimental Web Platform)”
            Firefox 54 – 需要在about:config里开启dom.moduleScripts.enabled选项。
            Edge 15 – 需要在about:flags里开启 Experimental JavaScript Features 选项


            需要将静态文件部署到服务器就能正常访问
        */
        import * as m1 from './m1.js'
        console.log(globalThis);
        console.log(m1);
    </script>

19.模块化数据语法汇总

<!-- 浏览器使用模块化方式一 -->
    <script type="module">
        /* 
            在浏览器中也可以使用JavaScript modules(模块功能)了。目前支持这一特性的浏览器包括:
            Safari 10.1.
            谷歌浏览器(Canary 60) – 需要在chrome:flags里开启”实验性网络平台功能(Experimental Web Platform)”
            Firefox 54 – 需要在about:config里开启dom.moduleScripts.enabled选项。
            Edge 15 – 需要在about:flags里开启 Experimental JavaScript Features 选项


            需要将静态文件部署到服务器就能正常访问
        */
        // 1.通用的导入方式
        // import * as m1 from './m1.js'
        // import * as m2 from './m2.js'
        // import * as m3 from './m3.js'
        // console.log(globalThis);
        // console.log(m1);
        // console.log(m3);
        // console.log(m2.default);

        // 2.结构赋值形式
        // import {school, teach} from './m3.js'
        // import {school as newName, teach} from './m3.js'
        // import {default as m2} from './m2.js'
        // console.log(newName, teach());
        // console.log(m2);

        // 3.简便形式 针对默认暴露
        // import m2 from './m2.js'
        // console.log(m2);
    </script>

    <!-- 浏览器使用模块化方式二 -->
    <script src="./app.js" type="module"></script>

20.babel对ES6模块化代码转化

<!-- 
        1.安装工具 babel-cli babel-preset-env browserify或(webpack)
            1)npm init

            2)cnpm install --save-dev @babel/core @babel/cli @babel/preset-env browserify
                https://www.babeljs.cn/
                https://github.com/browserify/browserify

            3)npx babel js --out-dir dist

            4)打包 npx browserify dist/app.js -o dist/bundle.js
                ES6转ES5后文件夹dist也是不能直接运行的需要打包
                报错Uncaught ReferenceError: require is not defined at app.js:3:1

            ********************************************
            在 npm version >= 5.2.0 开始,自动安装了npx。 
            npx是什么呢? npx 会帮你执行依赖包里的二进制文件。
            举个例子: 
                npm i webpack -D      //非全局安装
                //如果要执行 webpack 的命令
                ./node_modules/.bin/webpack -v
                有了 npx 之后
                npm i webpack -D    //非全局安装
                npx webpack -v 
                npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装。
            
                参考文章:https://www.jianshu.com/p/684329089d06
            ***********************************************
     -->
     <script src="./dist/bundle.js"></script>

ES7新特性

1.Array.prototype.includes

/* 
    1.Array.prototype.includes
    includes 方法用来检测数组中是否包含某个元素,返回布尔值
*/

const persons = ['张飞', '关羽', '赵云']
// console.log(persons.includes('张飞')); // true
// console.log(persons.includes('诸葛亮')); // false
/* 

2.指数操作符

    2.指数操作符
    在ES7中引入指数运算符 [**], 用来实现幂运算,功能与Math.pow 结果相同
*/
// console.log(2**4); // 16
// console.log(2**4 === Math.pow(2, 4)); // true

ES8新特性

1.async函数

2.await表达式

3.对象的扩展方法

Object.keys(school)
Object.values(school)
Object.entries(school)
Object.getOwnPropertyDescriptors(school)
const obj = Object.create(null, {
            name: {
                value: '北大',
                writable: true, // 是否可以重新赋值
                configurable: true, // 是否可以删除
                enumerable: true // 是否可以枚举
            },
            age: {}
        })

4.String.prototype.padStart

把指定字符串填充到字符串头部,返回新字符串。

语法 str.padStart(targetLength [, padString])

  • targetLength

    当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。

  • padString 可选

    填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 " "

    示例
    'abc'.padStart(10);         // "       abc"
    'abc'.padStart(10, "foo");  // "foofoofabc"
    'abc'.padStart(6,"123465"); // "123abc"
    'abc'.padStart(8, "0");     // "00000abc"
    'abc'.padStart(1);          // "abc"
    
    应用场景
    日期格式化:yyyy-mm-dd的格式:
    const now = new Date()
    const year = now.getFullYear()
    // 月份和日期 如果是一位前面给它填充一个0
    const month = (now.getMonth() + 1).toString().padStart(2, '0')
    const day = (now.getDate()).toString().padStart(2, '0')
    console.log(year, month, day)
    console.log( `${year}-${month}-${day}` ) //输入今天的日期 2021-12-31
    
    数字替换(手机号,银行卡号等)
    const tel = '18781268679'
    const newTel = tel.slice(-4).padStart(tel.length, '*')
    console.log(newTel) // *******8679
    

5.String.prototype.padEnd

把指定字符串填充到字符串尾部,返回新字符串。

语法 str.padStart(targetLength [, padString])

  • targetLength

    当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。

  • padString 可选

    填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 " "

    示例
    'abc'.padEnd(10);          // "abc       "
    'abc'.padEnd(10, "foo");   // "abcfoofoof"
    'abc'.padEnd(6, "123456"); // "abc123"
    'abc'.padEnd(1);           // "abc"
    
    应用场景

    在JS前端我们处理时间戳的时候单位是ms毫秒,但是,后端同学返回的时间戳则不一样是毫秒,可能只有10位,以s秒为单位。所以,我们在前端处理这个时间戳的时候,保险起见,要先做一个13位的补全,保证单位是毫秒。

    // 伪代码
    console.log(new Date().getTime()) // 时间戳 13位的
    timestamp = +String(timestamp).padEnd(13, '0')
    

ES9新特性

1.扩展运算符与rest参数

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

2.正则扩展-命名捕获分组

let str = '<a href="https://www.baidu.com">百度一下</a>';

        // 提取 URL 与 【标签文本】
        // const reg = /<a href="(.*)">(.*)<\/a>/

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

        // console.log(result);
        // console.log(result[0]);
        // console.log(result[1]);



        // 分组命名 添加 ?<url> 就会在group形成分组
        const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/
        
        const result = reg.exec(str);
        console.log(result);

3.正则扩展-反向断言

let str = 'jalsdfjlasf2234234你考虑撒就订饭了8888理解啊东风路卡啦啦啦'

        // 正向断言 提取8888
        // const reg = /\d+(?=理解)/; // ?= 固定写法
        // const result = reg.exec(str)
        // console.log(result);

        // 反向断言 提取8888
        const reg = /(?<=订饭了)\d+/   // ?<= 固定写法
        const result = reg.exec(str);
        console.log(result);

4.正则扩展-doAll模式

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>\s+<\/li>/g;
        const reg = /<li>(.*?)<a>(.*?)<\/a>(.*?)<p>(.*?)<\/p>(.*?)<\/li>/gs; // dotAll模式
        // const result = reg.exec(str)
        // console.log(result);

        let result;
        let data = [];
        while(result = reg.exec(str)) {
            console.log(result);
            data.push({title: result[1], time: result[2]})
        }

5.for await of

异步迭代器(for-await-of):循环等待每个Promise对象变为resolved状态才进入下一步。

我们知道 for...of 是同步运行的,看如下代码

function TimeOut(time){
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(time)
        }, time)
    })
}

async function test() {
    let arr = [TimeOut(2000), TimeOut(1000), TimeOut(3000)]
    for (let item of arr) {  
     console.log(Date.now(),item.then(console.log))
    }
}

test()

上面打印结果如下图

![](D:\Mason\Practice\EcmaScript-test\images\for of.png)

上述代码证实了 for of 方法不能遍历异步迭代器,得到的结果并不是我们所期待的,于是 for await of 就粉墨登场啦!

ES9 中可以用 for...await...of 的语法来操作

function TimeOut(time) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(time)
        }, time)
    })
}

async function test() {
    let arr = [TimeOut(2000), TimeOut(1000), TimeOut(3000)]
    for await (let item of arr) {
        console.log(Date.now(), item)
    }
}
test()

![](D:\Mason\Practice\EcmaScript-test\images\for await of.png)

for await of 环等待每个Promise对象变为resolved状态才进入下一步。所有打印的结果为 2000,1000,3000

6.Promise.prototype.finally()

Promise.prototype.finally() 方法返回一个Promise,在promise执行结束时,无论结果是fulfilled或者是rejected,在执行then()和catch()后,都会执行finally指定的回调函数。这为指定执行完promise后,无论结果是fulfilled还是rejected都需要执行的代码提供了一种方式,避免同样的语句需要在then()和catch()中各写一次的情况。

示例

new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('success')
        // reject('fail')
    }, 1000)
}).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
}).finally(() => {
    console.log('finally')
})

使用场景

需要每次发送请求,都会有loading提示,请求发送完毕,就需要关闭loading提示框,不然界面就无法被点击。不管请求成功或是失败,这个loading都需要关闭掉,这时把关闭loading的代码写在finally里再合适不过了

ES10新特性

1.对象方法拓展Object.fromEntries

// Object.fromEntries 是 Object.Entries的逆运算
        // Object.Entries将对象生成二位数组
        // Object.fromEntries将二维数组转换成对象

        // 二维数组
        const result = Object.fromEntries([
            ['name', 'M'],
            ['age', 78]
        ])
        // console.log(result); // {name: 'M', age: 78}

        // Map
        const m = new Map()
        m.set('name', 'T')
        // console.log(Object.fromEntries(m)); // {name: 'T'}

        // Object.entries ES8
        const arr = Object.entries({
            name: 'L'
        })
        console.log(arr);
        console.log(Object.fromEntries(arr));

案例1:Object 转换操作

const obj = {
    name: 'jimmy',
    age: 18
}
const entries = Object.entries(obj)
console.log(entries)
// [Array(2), Array(2)]

// ES10
const fromEntries = Object.fromEntries(entries)
console.log(fromEntries)
// {name: "jimmy", age: 18}

案例2:Map 转 Object

const map = new Map()
map.set('name', 'jimmy')
map.set('age', 18)
console.log(map) // {'name' => 'jimmy', 'age' => 18}

const obj = Object.fromEntries(map)
console.log(obj)
// {name: "jimmy", age: 18}

案例3:过滤

course表示所有课程,想请求课程分数大于80的课程组成的对象:

const course = {
    math: 80,
    english: 85,
    chinese: 90
}
const res = Object.entries(course).filter(([key, val]) => val > 80)
console.log(res) // [ [ 'english', 85 ], [ 'chinese', 90 ] ]
console.log(Object.fromEntries(res)) // { english: 85, chinese: 90 }

案例4:url的search参数转换

// let url = "https://www.baidu.com?name=jimmy&age=18&height=1.88"
// queryString 为 window.location.search
const queryString = "?name=jimmy&age=18&height=1.88";
const queryParams = new URLSearchParams(queryString);
const paramObj = Object.fromEntries(queryParams);
console.log(paramObj); // { name: 'jimmy', age: '18', height: '1.88' }

2.字符串方法扩展-trimStart-trimEnd

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

3.数组方法扩展-flat与flatMap

// 1.flag 平 参数默认是 铺平1层
        // const arr = [1,2,3,4,5,[6,7,8]]
        // console.log(arr.flat());
        // const arr = [1,2,3,4,5,[6,7,8,[9,10]]]
        // console.log(arr.flat(2))

        // 2.flatMap 是flat 和 Map组合
        const arr = [1,2,3,4];
        const result = arr.flatMap(item => [item * 10]);
        console.log(result);

4.Symbol.prototype.description

我们知道,Symbol 的描述只被存储在内部的 Description ,没有直接对外暴露,我们只有调用 Symbol 的 toString() 时才可以读取这个属性:

const name = Symbol('es')
console.log(name.toString()) // Symbol(es)
console.log(name) // Symbol(es)
console.log(name === 'Symbol(es)') // false
console.log(name.toString() === 'Symbol(es)') // true

现在可以通过 description 方法获取 Symbol 的描述:

const name = Symbol('es')
console.log(name.description) // es
name.description = "es2" // 只读属性 并不能修改描述符
console.log(name.description === 'es') // true
// 如果没有描述符 输入undefined
const s2 = Symbol()
console.log(s2.description) // undefined

5.修订 Function.prototype.toString()

以前函数的toString方法来自Object.prototype.toString(),现在的 Function.prototype.toString() 方法返回一个表示当前函数源代码的字符串。以前只会返回这个函数,不包含注释、空格等。

function foo() {
    // es10新特性
    console.log('imooc')
}
console.log(foo.toString()) 
// 打印如下
// function foo() {
//  // es10新特性
//  console.log("imooc");
// }

ES11新特性

1.私有属性

class Person {
            // 公有属性
            name = 'M';
            // 私有属性
            #age = 19;
            #weight;
            // 构造方法
            constructor(name, age, weight) {
                this.#weight = weight
            }
        }
        const girl = new Person('M', 19, '50kg')
        console.log(girl.name);
        // console.log(girl.#age);
        // console.log(girl.#weight);

2.Promise.allSettled

/* 
            Promise.all 全部成功才成功 有一个失败都返回失败
            Promise.allSettled 无论失败还是成功都返回成功状态
        */
        const p1 = new Promise((res, rej) => {
            setTimeout(() => {
                res('商品数量 - 1')
            }, 1000);
        })
        const p2 = new Promise((res, rej) => {
            setTimeout(() => {
                // res('商品数量 - 2')
                rej('商品2出错了')
            }, 1000);
        })

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

3.String.protorype.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>(.*?)<\/li>/gs; // dotAll模式

        const result = str.matchAll(reg);
        console.log(result);
        for (const iterator of result) {
            console.log(iterator);
        }

4.可选链操作符

// ?.
        function main(config) {
            const dbHost = config?.db?.host;
            console.log(dbHost);
        }


        main({
            db: {
                host: '192.168.1.1',
                username: 'M'
            }
        })

5.bigInt类型

// 大整形
        // let n = 512n
        
        // 大整形只能和大整形运算
        // console.log(123n + 1n);
        // console.log(n, typeof(n)); // 512n bigint


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

        // 大数值运算
        let max = Number.MAX_SAFE_INTEGER;
        console.log(max); // 9007199254740991
        console.log(max + 1); // 9007199254740992
        console.log(max + 2); // 9007199254740992 加几都返回 9007199254740992\


        console.log(BigInt(max));
        // 大整形只能和大整形运算
        console.log(BigInt(max) + BigInt(1));
        // 大整形只能和大整形运算
        console.log(BigInt(max) + BigInt(8));

6.import动态引入

const btn = document.querySelector('#btn');

btn.onclick = function () {
    // 动态引入
    import('./m1.js').then(module => {
        console.log(module);
        module.teach()
    })
}

7.绝对全局对象globalThis

console.log(globalThis); // 在nodejs环境是globalwindow环境是window

8.空值合并运算符(Nullish coalescing Operator)

空值合并操作符?? )是一个逻辑操作符,当左侧的操作数为 null或者undefined时,返回其右侧操作数,否则返回左侧操作数。

const foo = undefined ?? "foo"
const bar = null ?? "bar"
console.log(foo) // foo
console.log(bar) // bar
复制代码

与逻辑或操作符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如'',0,NaN,false)时。见下面的例子。

const foo = "" ?? 'default string';
const foo2 = "" || 'default string';
console.log(foo); // ""
console.log(foo2); // "default string"

const baz = 0 ?? 42;
const baz2 = 0 || 42;
console.log(baz); // 0
console.log(baz2); // 42

注意点

?? 直接与 AND(&&)和 OR(||)操作符组合使用是不可取的。

null || undefined ?? "foo"; // 抛出 SyntaxError
true || undefined ?? "foo"; // 抛出 SyntaxError

可选链与空值合并操作符一起使用

let customer = {
  name: "jimmy",
  details: { age: 18 }
};
let customerCity = customer?.city ?? "成都";
console.log(customerCity); // "成都"

ES12新特性

1.逻辑运算符和赋值表达式(&&=,||=,??=)

1.&&=

逻辑与赋值 x &&= y等效于:

x && (x = y);
复制代码

上面的意思是,当x为真时,x=y。具体请看下面的示例:

let a = 1;
let b = 0;

a &&= 2;
console.log(a); // 2

b &&= 2;
console.log(b);  // 0
复制代码

2.||=

逻辑或赋值(x ||= y)运算仅在 x 为false时赋值。

x ||= y 等同于:x || (x = y);

const a = { duration: 50, title: '' };

a.duration ||= 10;
console.log(a.duration); // 50

a.title ||= 'title is empty.';
console.log(a.title); // "title is empty"

复制代码

3.??=

逻辑空赋值运算符 (x ??= y) 仅在 xnullish[3] (nullundefined) 时对其赋值。

x ??= y 等价于:x ?? (x = y);

示例一

const a = { duration: 50 };

a.duration ??= 10;
console.log(a.duration); // 50

a.speed ??= 25;
console.log(a.speed); // 25
复制代码

示例二

function config(options) {
  options.duration ??= 100;
  options.speed ??= 25;
  return options;
}

config({ duration: 125 }); // { duration: 125, speed: 25 }
config({}); // { duration: 100, speed: 25 }
复制代码

2.String.prototype.replaceAll()

介绍

replaceAll() 方法返回一个新字符串,新字符串中所有满足 pattern 的部分都会被replacement 替换。pattern可以是一个字符串或一个RegExpreplacement可以是一个字符串或一个在每次匹配被调用的函数。

原始字符串保持不变。

示例

'aabbcc'.replaceAll('b', '.'); // 'aa..cc'

使用正则表达式搜索值时,它必须是全局的。

'aabbcc'.replaceAll(/b/, '.');
TypeError: replaceAll must be called with a global RegExp

这将可以正常运行:

'aabbcc'.replaceAll(/b/g, '.');
"aa..cc"

3.数字分隔符

欧美语言中,较长的数值允许每三位添加一个分隔符(通常是一个逗号),增加数值的可读性。比如,1000可以写作1,000

ES2021中允许 JavaScript 的数值使用下划线(_)作为分隔符。

let budget = 1_000_000_000_000;
budget === 10 ** 12 // true

这个数值分隔符没有指定间隔的位数,也就是说,可以每三位添加一个分隔符,也可以每一位、每两位、每四位添加一个。

123_00 === 12_300 // true

12345_00 === 123_4500 // true
12345_00 === 1_234_500 // true

小数和科学计数法也可以使用数值分隔符。

// 小数
0.000_001

// 科学计数法
1e10_000

数值分隔符有几个使用注意点。

  • 不能放在数值的最前面(leading)或最后面(trailing)。
  • 不能两个或两个以上的分隔符连在一起。
  • 小数点的前后不能有分隔符。
  • 科学计数法里面,表示指数的eE前后不能有分隔符。

下面的写法都会报错。

// 全部报错
3_.141
3._141
1_e12
1e_12
123__456
_1464301
1464301_

4.Promise.any

方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。

const promise1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("promise1");
      //  reject("error promise1 ");
    }, 3000);
  });
};
const promise2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("promise2");
      // reject("error promise2 ");
    }, 1000);
  });
};
const promise3 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("promise3");
      // reject("error promise3 ");
    }, 2000);
  });
};
Promise.any([promise1(), promise2(), promise3()])
  .then((first) => {
    // 只要有一个请求成功 就会返回第一个请求成功的
    console.log(first); // 会返回promise2
  })
  .catch((error) => {
    // 所有三个全部请求失败 才会来到这里
    console.log("error", error);
  });

只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

Promise.any()Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。