文章目录
- 1. 逻辑赋值操作符
- 2. 数字分隔符_
- 3. replaceAll
- 4. Promise.any
- 5. WeakRefs
- 6. FinalizationRegistry
1. 逻辑赋值操作符
逻辑赋值操作符 ??=、&&=、||=
let a = true
let b = true
a &&= b // a = a && b
a ||= b // a = a || b
obj.introduction ??= "这个人很懒"
// obj.introduction = obj.introduction ?? "这个人很懒"
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
3. replaceAll
所有匹配都会被替代项替换。模式可以是字符串或正则表达式,而替换项可以是字符串或针对每次匹配执行的函数。并返回一个全新的字符串。
- 使用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","*"))
// 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.
- 使用正则表达式
console.log(str.replace(/wish/g,"*")
// I * to * the * you * to * but if you * the * the witch * es,I won’t * the * you to * .
- 使用repalceAll()
console.log(str.replaceAll("wish","*"))
// 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吧!
-
Promise.all
有一个大的模块中需要多个模块传入数据,只有全部模块都传入数据完毕程序才向下执行; -
Promise.race
多个模块返回数据需要的时间不同,哪个模块最先返回数据就执行哪个模块; -
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
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
闭包使用多了会造成内存泄露,因为我们让内部临时变量永久化了,导致了闭包的形成。
之前的Set 和Map 中也存在这样的问题。
let s1 = new Set()
s1.add(obj)
s1.add("aaaaa")
obj = null
这段代码中obj 的引用次数为一,无法触发垃圾回收机制,如果程序中多次出现这种情况,垃圾占用内存越来越多,也会造成内存泄露!那这种情况应该怎么解决呢?
我们只要将Set改为WeakSet
注意:WeakSet 和Set 有些差别,
- WeakSet 只能使用复杂数据类型;
- Weak 系列不存在引用计数加一;
- Weak 系列不能使用for 循环和size()
let s1 = new WeakSet()
s1.add(obj)
// s1.add("aaaaa")
obj = null
同样的,使用普通的Map 数据机构,下面的代码中obj 不会被回收,因为m1 总的引用数 >0 。
let obj = {
name:"kerwin"}
let m1 = new Map()
m1.set(obj,"111111")
obj = null
// console.log(m1)
如果换成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)
虽然我们移除了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)
这个案例也就是WeakSet 和WeakMap 的用武之地了。当Dom节点被删除之后,相应的数据就会被回收。
强引用和弱引用:
一般来说,对象的引用都是强引用,这意味着只要有对象的引用,就不会被回收。
let obj = { name:"kerwin"}
let wobj = new WeakRef(obj)
// wobj.deref() 拿到原始对象
如果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")