看了这两篇,ECMAScript12你就懂了(二)

jeckson

共 2720字,需浏览 6分钟

 · 2021-08-07

三、??=  &&=  ||=

??=(逻辑空赋值运算符 (x ??= y) 仅在 x 是 nullish (null 或 undefined) 时对其赋值。)

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

const foo = null ?? 'default string';
console.log(foo); // default string

而??=,也从这个基础上又出了这个??=

const a = { duration50 };

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

a.speed ??= 25;
console.log(a.speed);
// 25

空值合并运算符从左至右求值。(结果非 null undefined 的表达式) ?? expr 被短路求值为左侧表达式,当左侧证明为既非 null 也非 undefined.

语法短路意味着 expr 部分尚未被求值,因此任何与其求值产生的相关副作用都不会生效(例如,如果 expr 是一个函数调用,则该调用将不会发生)。

逻辑空赋值的语法短路也意味着 x ??= y 等价于:

x ?? (x = y); // 理解空值合并运算符之后,再理解就简单啦。

x = x ?? (x = y)

&&=((x &&= y) 仅在 x 是 truthy (非假值,前面有介绍过<即除 false、0、""、null、undefined 和 NaN 以外皆为真值>) 时对其赋值。)

let a = 1;
let b = 0;

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

b &&= 2;
console.log(b);
// 0

x &&= y 等价于:

x && (x = y); 
x = x && (x = y)

||=((x &&= y) 仅在 x 是 falsy (假值<即false、0、""、null、undefined 和 NaN>) 时对其赋值。)

const a = { duration50title'' };

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

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

x ||= y 等价于:

x || (x = y); 
x = x || (x = y)
四、数字分隔符

允许数值字面量中间包含不连续_ ,以提高可读性。

1_000_000_000           // 1000000000
101_475_938.38          // 101475938.38

let a = 1_1; // 11
let a = 1__1 // 错误,只允许一个下划线作为数字分隔符
let a = 1_;  // 错误,分隔符不能在尾部 
let a = _1;  // 错误,分隔符不能在头部 

Number(1_1); // 11
Number('1_1'); // NaN

注意:分隔符不能在尾部和头部,只能在数字之间,只允许一个下划线作为数字分隔符,不可连续。

五、WeakRefs & FinalizationRegistry

WeakRef对象包含对对象的弱引用,这个弱引用被称为该WeakRef对象的target或者是referent。对对象的弱引用是指当该对象应该被GC回收时不会阻止GC的回收行为。而与此相反的,一个普通的引用(默认是强引用)会将与之对应的对象保存在内存中。只有当该对象没有任何的强引用时,JavaScript引擎GC才会销毁该对象并且回收该对象所占的内存空间。如果上述情况发生了,那么你就无法通过任何的弱引用来获取该对象。

Note: 对于WeakRef对象的使用要慎重考虑,能不使用就尽量不要使用

为什么尽量避免使用

正确使用WeakRef对象需要仔细的考虑,最好尽量避免使用。避免依赖于规范没有保证的任何特定行为也是十分重要的。何时、如何以及是否发生垃圾回收取决于任何给定JavaScript引擎的实现。GC在一个JavaScript引擎中的行为有可能在另一个JavaScript引擎中的行为大相径庭,或者甚至在同一类引擎,不同版本中GC的行为都有可能有较大的差距。GC目前还是JavaScript引擎实现者不断改进和改进解决方案的一个难题。

let obj = {a:1, b:2}; // 只要我们访问 obj 对象,这个对象就不会被垃圾回收

Weakref 实例具有一个方法 deref,该方法返回被引用的原始对象,如果原始对象已被收集,则返回 undefined 对象。

const ref = new WeakRef({ name'前端编程之家' });
let obj = ref.deref();
if (obj) {
  console.log(obj.name); // 前端编程之家
else{
  console.log('target deleted!')
}

FinalizationRegistry 提供了这样的一种方法:当一个在注册表中注册的对象被回收时,请求在某个时间点上调用一个清理回调。(清理回调有时被称为 finalizer )。

使用 FinalizationRegistry 对象可以在垃圾回收器回收对象时执行回调函数。

// 构建监听对象被垃圾回收器清除的回调
const registry = new FinalizationRegistry(heldValue => {
      console.log('----', heldValue);
});

const obj = {};
const token = {};

// 注册监听
registry.register(obj, "obj deleted!", token);

// 取消监听
registry.unregister(token);

// ---- obj deleted!

register 参数分别为:需要监听的对象、 执行回调函数的参数、 取消监听用的标识符


浏览 32
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报