• ES12 学习


    1. 逻辑赋值操作符

    逻辑赋值操作符 ??=、&&=、||=

    let a = true
    let b = true
    a &&= b  // a = a && b
    a ||= b  // a = a || b
    obj.introduction ??= "这个人很懒"
    // obj.introduction = obj.introduction ?? "这个人很懒"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. 数字分隔符_

    这个新特性是为了方便程序员看代码而出现的。如果数字比较大,那么看起来就不是那么一目了然。

    123,456,789 与 123_456_789 其中的‘ , ’ 和 ‘ _ ’作用一样,都只是为了方便看而存在的。

    let num = 123456789
    let num2 = 123456789
    console.log(num === num2) // true
    let num3 = 0b0010_1010
    let num4 = 0012_34_56
    let num5 = 0xa1_b2_c3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3. replaceAll

    所有匹配都会被替代项替换。模式可以是字符串或正则表达式,而替换项可以是字符串或针对每次匹配执行的函数。并返回一个全新的字符串。

    1. 使用replace()
    let str = `I wish to wish the wish you wish to wish,but if you wish
    the wish the witch wishes,I won't wish the wish you wish to wish.`
    console.log(str.replace("wish","*"))
    
    • 1
    • 2
    • 3

    // I * to wish the wish you wish to wish,but if you wish
    the wish the witch wishes,I won’t wish the wish you wish to wish.

    1. 使用正则表达式
    console.log(str.replace(/wish/g,"*")
    
    • 1

    // I * to * the * you * to * but if you * the * the witch * es,I won’t * the * you to * .

    1. 使用repalceAll()
    console.log(str.replaceAll("wish","*"))
    
    • 1

    // I * to * the * you * to * but if you * the * the witch * es,I won’t * the * you to * .

    4. Promise.any

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

    首先先回顾一下Promise.all / race / allSettled吧!

    1. Promise.all
      有一个大的模块中需要多个模块传入数据,只有全部模块都传入数据完毕程序才向下执行;

    2. Promise.race
      多个模块返回数据需要的时间不同,哪个模块最先返回数据就执行哪个模块;

    3. Promise.allSettled
      多个模块返回数据,不管有没有数据返回都会执行then() ,一般情况下我们会使用filter() 过滤得到能用的数据。

    现在我们要执行一个登录任务:设计一个登录 – 会员联盟系统,其中包括商超1,商超2,商超3,只要注册了一家的会员就能在另外两家商超使用会员,不然跳转到注册页面。

    let ajax1 = function(){
    return new Promise((resolve,reject)=>{
    resoLve("商超1")
    })
    let ajax2 = function(){
    return new Promise((resolve,reject)=>{
    resoLve("商超2")
    })
    let ajax3 = function(){
    return new Promise((resolve,reject)=>{
    resoLve("商超3")
    })
    Promise.any([ajax1(),ajax2(),ajax3()]).then(res=>{
    console.log(res)
    }).catch(err=>{
    console.log("err",err)
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    // 商超1

    any 和race 的不同点是:
    使用race 时如果先返回的Promise 对象是rejected ,那么将执行catch() ;

    使用any 时如果先返回一定是fulfilled 状态的Promise 对象,如果该模块所有的Promise 对象都为rejected 状态,那么将执行catch()。
    在这里插入图片描述

    5. WeakRefs

    在一般情况下,对象的引用是强引用的,这意味着只要持有对象的引用,它就不会被垃圾回收。只有当该对象没有任何的强引用时,垃圾回收才会销毁该对象并且回收该对象所占的内存空间。而WeakRef允许您保留对另一个对象的弱引用,而不会阻止被弱引用对象被垃圾回收。

    在ES6学习中,我们学习了Set 和Map 两种数据结构,其实还有WeakSet 和WeakMap 两种,在ES12 又推出了WeakRef ,我们在这里统一学习一下Weak 系列的数据结构。

    垃圾回收机制学习

    let obj = {
    name:"kerwin"
    }
    let obj1 = obj
    obj = null
    
    • 1
    • 2
    • 3
    • 4
    • 5

    闭包使用多了会造成内存泄露,因为我们让内部临时变量永久化了,导致了闭包的形成。

    之前的Set 和Map 中也存在这样的问题。

    let s1 = new Set()
    s1.add(obj)
    s1.add("aaaaa")
    obj = null
    
    • 1
    • 2
    • 3
    • 4

    这段代码中obj 的引用次数为一,无法触发垃圾回收机制,如果程序中多次出现这种情况,垃圾占用内存越来越多,也会造成内存泄露!那这种情况应该怎么解决呢?

    我们只要将Set改为WeakSet

    注意:WeakSet 和Set 有些差别,

    1. WeakSet 只能使用复杂数据类型;
    2. Weak 系列不存在引用计数加一;
    3. Weak 系列不能使用for 循环和size()
    let s1 = new WeakSet()
    s1.add(obj)
    // s1.add("aaaaa")
    obj = null
    
    • 1
    • 2
    • 3
    • 4

    同样的,使用普通的Map 数据机构,下面的代码中obj 不会被回收,因为m1 总的引用数 >0 。

    let obj = {
    name:"kerwin"}
    let m1 = new Map()
    m1.set(obj,"111111")
    obj =  null
    // console.log(m1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果换成WeakMap 则obj 会被回收。


    现在有一个DOM 节点,如果使用Map 存储该节点,当该节点被删除之后,但是不会出发垃圾回收机制;但是使用WeakMap ,obj 就会被回收。

    let wmap = new WeakMap()
    let like = document.getElementById("like")
    wmap.set(like,{click:0})
    like.onclick function(){
    Let times wmap.get(like)
    times.click++
    }
    setTimeout(()=>{
    document.body.removeChild(like)
    // like =null
    console.log(like)
    },2000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    虽然我们移除了like 但是因为我们先将like Dom 节点赋值给了like 变量,所以我们还是能够访问到like ,如果like = null 那么like 就会被回收,就访问不到like 了。

    let wmap = new WeakMap()
    wmap.set(document.getElementById("like"),{click:0})
    document.getElementById("like").addEventListener("click",function(){
    let times =  wmap.get(document.getElementById("like"))
    times.click++
    },false)
    setTimeout(()=>{
    document.body.removechild(document.getElementById("like"))
    },2000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这个案例也就是WeakSet 和WeakMap 的用武之地了。当Dom节点被删除之后,相应的数据就会被回收。

    强引用和弱引用
    一般来说,对象的引用都是强引用,这意味着只要有对象的引用,就不会被回收。

    let obj = { name:"kerwin"}
    let wobj = new WeakRef(obj)
    // wobj.deref() 拿到原始对象
    
    • 1
    • 2
    • 3

    如果obj = null ,那么wobj.deref() 就拿不到对象,这就是对象的弱引用。wobj.deref() 这种写法就可以替换上面代码中的document.getElementById(“like”)

    6. FinalizationRegistry

    了解即可,建议少用。

    清理器注册表功能FinalizationRegistry,用来指定目标对象被垃圾回收机制清除以后,所要执行的回调函数。

    let obj = { name:"kerwin"}
    let registry = new FinalizationRegistry(data=>{
    console.log("销毁了",data)
    })
    registry.register(obj,"11111111111111")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

  • 相关阅读:
    Harbor webhook从原理到构建
    C++内存分区模型
    你也可以很硬核「GitHub 热点速览 v.22.13」
    图像处理之matlab中fspecial函数用法详解
    【linux基础(1)】
    基于HFSS的T型功分波导设计
    [模电课程设计]基于TCP7107的数字式温度计设计
    etcd中version,revision,mod_revision,create_revision的区别
    echarts优秀使用案例
    周涛:在大数据沙滩上捡拾“珍珠”|奋斗者正青春
  • 原文地址:https://blog.csdn.net/2302_79523175/article/details/137403244