Three,?? && = = | | =

?? =(the logical null assignment operator (x?? = y) only if x is nullish (null or undefined).

ES11 proposes the null-value merge operator?? The null-value merge operator (??) Is a logical operator that returns the right-hand operand if the left-hand operand is null or undefined, otherwise returns the left-hand operand.

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

And???? =, and from that comes this?? =

const a = { duration: 50 }; a.duration ?? = 10; console.log(a.duration); // 50 a.speed ?? = 25; console.log(a.speed); / / 25Copy the code

The null-value merge operator evaluates from left to right. An expression whose result is not null or undefined. Expr is short-circuited to a left expression when the left proves to be neither null nor undefined.

A syntax short circuit means that the EXPR part has not yet been evaluated, so any side effects associated with its evaluation will not take effect (for example, if expr was a function call, the call would not occur).

The syntactic short circuit of logical null assignment also means that x?? = y is equivalent to:

x ?? (x = y); // Once you understand the null-value merge operator, it's easy to understand. x = x ?? (x = y)Copy the code

&&=((x &&= y) only assigns to x if it is truthy (not false, as described earlier < that is, true > except false, 0, “”, null, undefined, and NaN).

let a = 1; let b = 0; a &&= 2; console.log(a); // 2 b &&= 2; console.log(b); / / 0Copy the code

X &&= y is equivalent to:

x && (x = y); 
x = x && (x = y)
Copy the code

| | = (&& (x = y) only in x is falsy (false value < that is false, 0, “”, null, and undefined and NaN >) to its assignment.)

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

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

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

X | | = y is equivalent to:

x || (x = y); 
x = x || (x = y)
Copy the code

4. Numeric delimiters

Allow numeric literals to contain discontinuous _ in the middle to improve readability.

1_000_000_000 // 1000000000 101_475_938.38 // 101475938.38 let a = 1; // 11 let a = 1__1 // error, only one underscore is allowed as number separator let a = 1_; // error, the delimiter cannot be in the end let a = _1; // error, the separator cannot be in the header Number(1_1); // 11 Number('1_1'); // NaNCopy the code

Note: The separator can not be in the tail and the head, only between the number, only allow one underscore as the number separator, not contiguous.

WeakRefs & FinalizationRegistry

A WeakRef object contains a weak reference to the object, which is called the target or referent of the WeakRef object. A weak reference to an object means that it does not prevent the GC from collecting when the object should be collected by the GC. In contrast, a normal reference (strong by default) keeps its corresponding object in memory. Only if the object does not have any strong references does the JavaScript engine GC destroy the object and reclaim the memory occupied by the object. If that happens, then you can’t get the object through any weak references.

Note: The use of WeakRef object should be carefully considered, and try not to use it if possible

Why avoid it

Proper use of WeakRef objects requires careful consideration and is best avoided. It is also important to avoid relying on any particular behavior that is not guaranteed by the specification. When, how, and if garbage collection occurs depends on the implementation of any given JavaScript engine. GC behavior in one JavaScript engine can be very different in another JavaScript engine, or even in the same type of engine, different versions of GC behavior can be very different. GC is still a challenge for JavaScript engine implementers to continually improve and improve their solutions.

let obj = {a:1, b:2}; // As long as we access the obj object, it is not garbage collected

A Weakref instance has a method, deref, that returns the referenced original object or undefined object if the original object has been collected.

Const ref = new WeakRef({name: 'home of front-end programming'}); let obj = ref.deref(); if (obj) { console.log(obj.name); } else{console.log('target deleted! ')}Copy the code

FinalizationRegistry provides a way to request a cleanup callback at some point in time when an object registered in the registry is reclaimed. Cleanup callbacks are sometimes called finalizers.

You use FinalizationRegistry objects to perform callback functions when the garbage collector collects the object.

Const registry = new FinalizationRegistry(heldValue => {console.log('----', heldValue); }); const obj = {}; const token = {}; Register (obj, "obj deleted!") , token); // Unregister registry. Unregister (token); // ---- obj deleted!Copy the code

Register parameters are the object to listen on, the parameter to execute the callback function, and the identifier to cancel the listening

Questions welcome to comment!