ES7-ES12使用方法

202 阅读10分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

ES2016(ES7)

1. Array.prototype.includes()

判断数组里是否有特定的值,传回true/false

语法

arr.includes(searchElement[, fromIndex])

fromIndex:可选参数,默认是0

		let arr = ['es7','es8','es9','es10','a']
		console.log(arr.includes("es7"));   //true
		console.log(arr.includes("es12"));   //false
		console.log(arr.includes("es7",2));   //false

注意点

  • 区分大小写
		let arr = ['es7','es8','es9','es10','a']

		console.log(arr.includes("A"))   //false

只能判断简单类型的数据,对于复杂类型的数据,比如对象,二维数组,这些都无法判断

		let arr = ['es6', ['es7', 'es8'], 'es9',{name:"syl"}]
		console.log(arr.includes(["es7", "es8"])); // false
		console.log(arr.includes({name:"syl"})); // false
  • 和indexOf的区别 ​ indexOf不能识别NaN
        let arr = ['es7','es8','es9','es10',NaN]
        console.log(arr.indexOf(NaN))   //-1
        console.log(arr.includes(NaN))   //true

总结

如果只想知道数组里包不包含一个值,使用includes,如果想知道具体数值缩在的位置,使用indexOf

2. 幂运算符

函数实现

        function pow(x,y){
            let result = 1
            for(let i = 0;i<y;i++){
                result *= x
            }
            return result
        }
       console.log( pow(2,10))   //1024

Math实现

      console.log(Math.pow(2,10))

使用幂运算符

       console.log(2**10)

注意点

  • NaN不可求幂
       console.log(NaN ** 1)  //NaN
  • 幂运算符的两个*之间不能出现空格,否则语法会报错

ES2017(ES8)

1. Object.values()

Object.values()方法返回一个数组,成员是参数对象(不包含继承的)所有可遍历的键值。

       let obj= {
           name:liHua,
           age:18,
           weight:40,
       }
       console.log(Object.values(obj))   //['liHua', 18, 40]
       let obj= {
           name:"liHua",
           age:18,
           weight:40,
           hobby:{
               piano:true,
               Calligraphy:true
           }
       }
       console.log(Object.values(obj))   //['liHua', 18, 40,{piano: true, Calligraphy: true}]

2. Object.entries()

Object.entries() 方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值对数组。

       let obj2 = {
           name: "liHua",
           age: 18
       }
       console.log(Object.entries(obj2))  //[["name","liHua"],["age",18]]
       let obj2 = {
           name: "liHua",
           age: 18,
           information: {
               weight: 40,
               piano: true
           }
       }
       console.log(Object.entries(obj2))  
       //打印结果
       [["name","liHua"],["age",18],["information",{weight: 40,panio: true}]]

3. Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors() 方法用来获取一个对象的所有自身属性的描述符。

  • value:当前对象的默认值
  • writable:表示当前对象是否可以修改
  • enumerable:表示当前这个属性是否可以出现在对象的枚举属性中
  • configurable:表示当前这个对象的属性是否能用delete删除
        let obj3 = {
            name: "liHua",
            age: 18,
        };
        let desc = Object.getOwnPropertyDescriptors(obj3);
        console.log(desc);
        
    //打印结果
        {
            name: {
                value: 'liHua',
                writable: true,
                enumerable: true,
                configurable: true
            },
            age: {
                value: 18,
                writable: true,
                enumerable: true,
                configurable: true
            }
        }

对象的属性如何设置和修改呢,可以使用ES5提供的Object.defineProperty()

        Object.defineProperty(obj3, "name", {
            value: "hanMeiMei",
            writable: true,
            enumerable: true,
            configurable: true,
        })
        console.log(obj3)
        //打印结果
        {name: 'hanMeiMei', age: 18}

当我们将writable设置为false,configurable设置为false时,对象的值不能被修改和删除。 当enumerable设置为false,对象的属性不可被枚举,所以遍历对象取不到name的键,只能取到age

        Object.defineProperty(obj3, "name", {
            value: "liHua",
            writable: false,
            enumerable: false,
            configurable: false,
        })
        
        console.log(obj3.name)   //打印结果:liHua
        obj3.name = "hanMeiMei"
        console.log(obj3.name)  //打印结果:liHua
        delete obj3.name
        console.log(obj3.name)  //打印结果:liHua
        
        for(let key in obj3){
            console.log(key)   //打印结果:age
        }

4. String.prototype.padStart()

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

  • targetLength:当前字符串需要填充到的目标长度,如果这个数值小于字符串的长度,则返回当前字符串本身
  • padString:可选,选择填充的字符串,默认值是空字符串。如果字符串太长,填充后长度超过了目标值,则只保留左侧的长度,剩下部分被截断。
        console.log("liHua".padStart(10))  //"  syl"
        console.log("liHua".padStart(10,"123456789"))   //"12345liHua"

应用场景

  • 日期格式化:yyyy-mm-dd格式
    var month = date.getMonth() + 1
	var strDate = date.getDate()
	if (month >= 1 && month <= 9) {
		month = '0' + month
	}
	if (strDate >= 0 && strDate <= 9) {
		strDate = '0' + strDate
	}

or

	let month = format_date.getMonth() + 1 < 10 ? `0${format_date.getMonth() + 1}` : format_date.getMonth() + 1;
			let day = format_date.getDate() < 10 ? `0${format_date.getDate()}` : format_date.getDate();

可以换成

let year = ((new Date().getMonth()) + 1).toString().padStart(2,"0")

隐藏手机号/银行卡等

        let tel = "18600967266"
        console.log(tel.slice(-4).padStart(tel.length,"*"))  //*******7266

5. String.prototype.padEnd()

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

        console.log("liHua".padEnd(10))   //"liHua     "
        console.log("liHua".padEnd(1))   //liHua

应用场景

js处理时间戳单位是毫秒ms,后端返回的时间如果不是毫秒ms。所以我们在处理这个时间戳的时候,保险起见,要先做一个13位的补全。

        console.log(new Date().getTime().toString().padEnd(13,"0"))

6. async/await

我们都知道使用 Promise 能很好地解决回调地狱的问题,但如果处理流程比较复杂的话,那么整段代码将充斥着 then,语义化不明显,代码不能很好地表示执行流程,那有没有比 Promise 更优雅的异步方式呢?那就是async/await!

        function foo() {
            return "liHua"
        }
        console.log(foo())  //liHua

添加async后,返回的是一个Promise对象

        async function foo() {
            return "liHua"
        }
        console.log(foo())
        
        // 打印结果
        [[Prototype]]: Promise
        [[PromiseState]]: "fulfilled"
        [[PromiseResult]]: "liHua"

async函数中使用await,那么await这里的代码就会变成同步的了,意思就是说只有等await后面的Promise执行完成得到结果才会继续下去,await就是等待。请看下面的示例

        function timeout() {
            return new Promise(resolve => {
                setTimeout(() => {
                    console.log(1)
                    resolve()
                }, 1000)
            })
        }

        // 不加async和await是2、1   加了是1、2
         async function foo() {
            await timeout()
            console.log(2)
        }
        foo()

假如有这样一个使用场景:需要先请求 a 链接,等返回信息之后,再请求 b 链接的另外一个资源。下面代码展示的是使用 fetch 来实现这样的需求,fetch 被定义在 window 对象中,它返回的是一个 Promise 对象。

        fetch("https://www.csdn.net/")
            .then(response => {
                console.log("response")
                return fetch("https://juejin.cn/")
            })
            .then(response => {
                console.log(response)
            })
            .catch(error => {
                console.log(error)
            })

虽然上述代码可以实现这个需求,但语义化不明显,代码不能很好地表示执行流程。基于这个原因,ES8 引入了 async/await,这是 JavaScript 异步编程的一个重大改进,提供了在不阻塞主线程的情况下使用同步代码实现异步访问资源的能力,并且使得代码逻辑更加清晰。

            async function foo(){
                try{
                    let response1 = await fetch("https://www.csdn.net/")
                    console.log("response1")
                    let response2 = await fetch("https://juejin.cn/")
                    console.log(response2)
                }catch (error){
                    console.log(error)
                }
            }
            foo()

注意点

  • await只能子安async标记的函数内部使用,单独使用会触发Syntax error
  • await后面需要跟异步操作,不然就没有意义。且await后面的Promise对象不必写then,因为await的作用之一就是获取后面Promise对象成功状态传递出来的参数。

缺陷

Async/await 让你的代码看起来是同步的,在某种程度上,也使得它的行为更加地同步。 await 关键字会阻塞其后的代码,直到promise完成,就像执行同步操作一样。它确实可以允许其他任务在此期间继续运行,但您自己的代码被阻塞。

这意味着您的代码可能会因为大量await的promises相继发生而变慢。每个await都会等待前一个完成,而你实际想要的是所有的这些promises同时开始处理(就像我们没有使用async/await时那样)。

ES2018(ES9)

1. Object.Rest & Object.Spread

        let input = {
            a: 1,
            b: 2,
            c: 3,
        }
        let output = {...input}
        console.log(output)   //{a: 1, b: 2, c: 3}

注意点

  • 如果存在相同的属性名,只有最后一个会生效
        let input = {
            a: 1,
            b: 2,
            c: 3,
        }
        let output = { ...input, c: 4 }
        console.log(output)   //{a: 1, b: 2, c: 4}
  • 如果属性的值是一个对象的话,该对象的引用会被拷贝,而不是生成一个新的对象。
        let obj4 = {
            x: { y: 10 }
        }
        let copy1 = {...obj4}
        let copy2 = {...obj4}
        obj4.x.y = "liHua"
        console.log(copy1,copy2)  //x: {y: 'liHua'} , x: {y: 'liHua'}  
        console.log(copy1.x === copy2.x)  //true
  • 当对象 key-value 不确定的时候,把必选的 key 赋值给变量,用一个变量收敛其他可选的 key 数据,这在之前是做不到的。注意,rest 属性必须始终出现在对象的末尾,否则将抛出错误。
        let input = {
            a: 1,
            b: 2,
            c: 3,
        }
        let { a, ...rest } = input
        let output = { a, rest }
        console.log(output)    //{a:1,rest:{b: 2,,c: 3}}

2. 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 (let item of arr) {
                console.log(Date.now(), item.then(console.log))
            }
        }

        test()
        // 打印结果
        //1640830034005 Promise {<pending>}
        //1640830034005 Promise {<pending>}
        //1640830034005 Promise {<pending>}
        //1000
        //2000
        //3000
        

上述代码证实了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 await (let item of arr) {
                console.log(Date.now(), item)
            }
        }

        test()
        //打印结果
        // 1640830494750 2000
        // 1640830494750 1000
        // 1640830495738 3000

for await of 等待每一个Promise对象变为fulfilled状态才进入下一步。

3. Promise.prototype.finally()

Promise.prototype.finally()方法会返回一个Promise对象,在Promise执行结束之后,无论结果是fulfilled或者rejected,在执行then()和catch()后,都会执行finally指定的回调函数。

        new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve("resolve")
            },1000)
        }).then(res=>{
            console.log(res)
        }).catch(error=>{
            console.log(error)
        }).finally(()=>{
            console.log("finally")
        })
        //打印结果
        // resolve
        // finally

应用场景

  • loading关闭 需要每次发送请求,都会有loading提示,请求发送完毕,就需要关闭loading提示框,也就是说不管成功或者失败,这个loading都需要关掉,这时吧关闭loading的代码写在finally里再合适不过了。

ES2019(ES10)

1. Object.fromEntries()

将键值对列表转换为一个对象

        let obj5 =  Object.fromEntries([
            ["foo", 1],
            ["bar", 2]
        ])
        console.log(obj5)  //{foo: 1, bar: 2}

案例1:Object转换操作

        let obj6 = {
            name:"liHua",
            age:18
        }
        let entries = Object.entries(obj6)
        console.log(entries)  //[['name', 'liHua'],['age', 18]]
        
        let fromEntries = Object.fromEntries(entries)
        console.log(fromEntries)   //{name: 'liHua', age: 18}

案例2:Map转Object

        let map = new Map()
        map.set("name","liHua")
        map.set("age",18)
        console.log(map)    //{'name' => 'liHua', 'age' => 18}

        let obj7 = Object.fromEntries(map)
        console.log(obj7)  //{name: 'liHua', age: 18}

案例3:过滤

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

案例4:url的serch参数转换

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

2.Array.prototype.flat()

flat方法会按照一个可指定的深度递归遍历数组,并将所有元素钰遍历的字数组的元素合并为一个新数组返回。

语法

let newArray = arr.flat([depth])
指定要提取嵌套数组的结构深度,默认值为 1

示例

  • 指定参数
        let arr1 = [0, 1, 2, [[3, 4]]]
        console.log(arr1.flat())   //[0, 1, 2, [3, 4]]
        console.log(arr1.flat(2))   //[0, 1, 2, 3, 4]
  • 展开全部
        var arr2 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
        console.log(arr2.flat(Infinity))   //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 移出数组中的空项
        var arr3 = [1,2,,4,5]
        console.log(arr3.flat())  //[1, 2, 4, 5]

3. Array.prototype.flatMap()

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。从方法的名字上也可以看出来它包含两部分功能一个是 map,一个是 flat(深度为1)。

语法

var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {
    // 返回新数组的元素
}[, thisArg])

  • callback:

    可以生成一个新数组中的元素的函数,可以传入三个参数

  • currentValue

    当前正在数组中处理的元素

  • index

    可选,数组中当前正在处理元素的索引值

  • array

    可选,被调用的map数组

  • thisArg

    指定callbback函数时使用的this值

示例

  • 简单使用
        let num1 = [1, 2, 3]
        console.log(num1.map(item => [item * 2])) //[[2],[4],[6]]
        console.log(num1.flatMap(item => [item * 2]))   //[2,4,6]
  • map和flatMap的区别对比
        let arr4 = ["早上你吃的什么", "", "吃的包子"]
        console.log(arr4.map(item=>item.split("")));

打印结果 image

        let arr4 = ["早上你吃的什么", "", "吃的包子"]
        console.log(arr4.flatMap(item=>item.split("")))
        //打印结果
        //['早', '上', '你', '吃', '的', '什', '么', '吃', '的', '包', '子']

4. String.prototype.trimStart

trimStart() 方法从字符串的开头删除空格,trimLeft()是此方法的别名。

let str = '   foo  '
console.log(str.length) // 8
str = str.trimStart() // 或str.trimLeft()
console.log(str.length) // 5

5. String.prototype.trimEnd

trimEnd() 方法从一个字符串的右端移除空白字符,trimRight 是 trimEnd 的别名。

let str = '   foo  '
console.log(str.length) // 8
str = str.trimEnd() // 或str.trimRight()
console.log(str.length) // 6

6. Symbol.prototype.description

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

        let name2 = Symbol("xiaobai")
        console.log(name2.toString())   //Symbol(xiaobai)
        console.log(name2)   //Symbol(xiaobai)
        console.log(name2 === "Symbol(xiaobai)")   //false
        console.log(name2.toString() === "Symbol(xiaobai)")   //true

ES2020(ES12)

1.空值合并运算符

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

        let str1 = undefined ?? "str1"
        let str2 = null ?? "str2"
        console.log(str1)   //str1
        console.log(str2)   //str2

与逻辑或的区别

逻辑或会在左侧造作数为false的时候,返回右侧操作数。

        console.log(undefined || "xiaobai")   //xiaobai
        console.log(undefined ?? "xiaobai")    //xiaobai

        console.log(null || "xiaobai")    //xiaobai
        console.log(null ?? "xiaobai")    //xiaobai

        console.log(0 || "xiaobai")    //xiaobai
        console.log(0 ?? "xiaobai")   //0

        console.log(false || "xiaobai")   //xiaobai
        console.log(false ?? "xiaobai")    /false

        console.log("" || "xiaobai")   //xiaobai
        console.log("" ?? "xiaobai")   //""(空字符串)

        console.log(NaN || "xiaobai")   //xiaobai
        console.log(NaN ?? "xiaobai")   //NaN