This is the second and final article in the series. For more information, see the first complete ES2021 feature Set (1).


22. Indexable collections

An array of

Array creation method

[element0, element1, ..., elementN]
new Array(element0, element1[, ...[, elementN]])
new Array(arrayLength)
Copy the code

Static attributes

  • get Array[@@species]

A static method

  • Array.from(arrayLike [, mapFn [, thisArg]]) generates a new Array from the array-like iterated object, equivalent toArray.from(obj).map(mapFn, thisArg)
  • Array.isArray(value) Checks whether the parameter is an Array
  • Array.of(element0[, element1[,…[, elementN]]) adds parameters to the new Array

Instance attributes

  • The value length is a 32-bit unsigned integer between 0 and 2^32-1. Deleting length dismisses extra elements

Instance attributes

The iteration

  • arr.entries()
  • Arr.keys () returns subscripts, such as 0,1,2
  • arr.values()
  • Arr. Every (callback(Element [, index[, array]])[, thisArg]) returns if all elements pass the callback test. The callback function stops once it returns false and does not test deleted or unassigned elements
  • Arr. Filter (callback(Element [, index, [array]])[, thisArg]) creates a new array containing the elements that pass the test
  • Arr. ForEach (callback(currentValue [, index [, array]])[, thisArg])
  • Arr. Map (function callback(currentValue[, index[, array]]) {// return element for new_array}[, thisArg]) returns a new array
  • Arr. Reduce (callback(Accumulator, currentValue, [, index[, array]])[, initialValue]) An error is reported without an initial value; If there is only one element in the array with no initial value, the callback will not be executed. respectively
    • The initialValue initial value
    • If there is no initial value, the accumulator is the first element and the current value is the second. Otherwise, the accumulator is the initial value and the current value is the first
    • The current value currentValue
    • array
  • Arr. ReduceRight (Callback (Accumulator, currentValue[, Index [, array]])[, initialValue]) Perform the reducer from right to left

Does it include

  • Arr. Find (callback(Element [, index[, array]])[, thisArg]
  • Arr. FindIndex (callback(Element [, index[, array]])[, thisArg]) returns the first eligible subscript
  • Arr.indexof (searchElement[, fromIndex]) searches backwards to return the first matching index
  • Arr. LastIndexOf (searchElement[, fromIndex]) returns the first matching index by looking backwards
  • Arr.includes (valueToFind[, fromIndex]) Returns a Boolean value
  • Arr. Some (callback(Element [, index[, array]])[, thisArg]

Add or delete

  • Arr.pop () removes the last element and returns that element, or undefined if the array is empty
  • Arr. push([element1[,…[, elementN]]) adds elements from the end and returns the length of the array
  • Arr. Unshift (element1[,…[, elementN]]) adds elements from the front, returning the length of the array
  • Arr.shift () removes the uppermost element and returns the removed element, undefined if the array is empty

The sorting

  • Arr. Reverse () the reverse
  • arr.sort(function(a, b) { return a – b; }); Sort from smallest to largest

other

  • Const new_array = old_array.concat([value1[, value2[,…[, valueN]]]]) merges two or more arrays and returns a new array. The argument can be an array or a value; if null, a shallow copy of the array is returned
  • Arr. CopyWithin (target[, start[, end]]) shallow copies part of the array to another location in the same array, returns the modified array, respectively
    • Target Indicates the target position, or from the back if it is negative
    • Start Indicates the start position of the source data. The value is negative from the back. The default value is 0
    • End metadata ends, negative from last, default array length
  • Arr.fill (value[, start[, end]]) fills the array with a fixed value and returns the modified array, respectively
    • Value Specifies the value to fill
    • Start Specifies the starting position. The default value is 0, and the value is negative
    • End Specifies the end position of the array. The default array length is negative
  • Arr. slice([start[, end]]) shallowly copies a range of elements into the new array
  • Let arrDeletedItems = array.splice(start[, deleteCount[, Item1 [, Item2 [,…]]]]) to modify the array by deleting or replacing elements
  • Const new_array = old_array.concat([value1[, value2[,…[, valueN]]]]) Const new_array = old_array.concat([value1[, value2[,…[, valueN]]]]) The argument is an array or a value. If omitted, a shallow copy of the existing array is returned.
  • Arr.join ([separator]) concatenates array elements into a string using separators, which default to commas
  • Arr.tostring () returns a string of array elements

TypedArray

TypedArray is an object that reads and writes raw binary data from buffers, mainly audio, video, WebSockets and other raw data.

Js divides the process of reading and writing buffer into two parts: one is the Buufer implemented by ArrayBuffer, which is a fixed length binary data block and cannot be operated directly; The second part is the view. Buffers can be manipulated in different formats, as shown below. Views include TypedArray and DataView, described here, in detail in their respective sections.

There is a TypedArray constructor in JS that acts as a [[prototype]] for various specific typed arrays, but is not directly exposed to the user, depending on the type of each element of a particular array, including the following TypedArray objects, which are initialized to 0 once created

  • Int8Array Array of 8-bit signed integers ranging from -128 to 127
  • Uint8Array is an array of 8-bit unsigned integers ranging from 0 to 255
  • Uint8ClampedArray is an 8-bit unsigned integer with a range of 0 to 255. The difference between Uint8Array and Uint8Array is that when the Uint8ClampedArray is overflowing, it is handled according to The ToUint8Clamp, that is, round the decimal and replace the overflowing value with the nearest 0 or 255.
  • Int16Array A 16-bit binary integer
  • Uint16Array 16-bit unsigned integer
  • Int32Array A 32-bit binary integer
  • Uint32Array 32 – bit unsigned integer
  • Float32Array Indicates the number of 32-bit floating points
  • Float64Array Indicates the number of 64-bit floating points
  • BigInt64Array A 64-bit signed integer
  • BigUint64Array 64-bit unsigned integer

Because TypedArray is similar to an array, I will not expand it when I refer to the related property methods below

The constructor

new TypedArray();
new TypedArray(length);
new TypedArray(typedArray);
new TypedArray(object);
new TypedArray(buffer [, byteOffset [, length]]);
Copy the code

Static attributes

  • Typedarray.bytes_per_element represents the length of an array element in bytes, for example
Int8Array.BYTES_PER_ELEMENT; / / 1Copy the code
  • Typedarray. name Is a string representing the constructor name

A static method

  • TypedArray.from(source[, mapFn[, thisArg]])
  • TypedArray.of(element0[, element1[, …[, elementN]]])

Instance attributes

  • TypedArray. Prototype. Buffer reference ArrayBuffer
  • TypedArray. Prototype. ByteLength bytes
  • TypedArray. Prototype. ByteOffset from ArrayBuffer offset
  • TypedArray. Prototype. Length element number

Instance attributes

See MDN, which differs slightly from Array in that there is no push method.

23. Use key sets

Map

Map objects have key-value pairs and remember the order in which they were added. The keys and values can be of all types, including the object and the original value.

Objects vs Maps

Including the following differences

  • Default key: Map none, except passObject.create(null)Each object will have a prototype containing a default key
  • Key, Map can be any value, Object can only be a string or symbol
  • The Map is added in the order of keys. Although the Object is ordered now, it was unordered in the previous version, and the sorting is complex. It is not recommended to rely on attribute attributes
  • The size and the number of maps can be obtained by using the size attribute. Object must be obtained manually
  • Iterability, Map can iterate, Object does not iterate and therefore cannot use for… Of,
  • Performance: Map is optimized for frequent addition and deletion, while Object is not optimized

The constructor

new Map([iterable])
Copy the code

Instance attributes

  • Size Returns the number of key-value pairs

Instance methods

  • myMap.clear(); Remove all elements
  • Mymap.delete (key) removes a specific element
  • Mymap.get (key) gets the specific element
  • Mymap. has(key) determines whether an element is present
  • Mymap.set (key, value) sets the element

The iteration

  • myMap.keys()
  • myMap.values()
  • myMap.entries()
  • Mymap.foreach (callback([value][, key][, map])[, thisArg]), e.g
function logMapElements(value, key, map) {
    console.log(`map.get('${key}') = ${value}`)
}
new Map([['foo', 3], ['bar', {}], ['baz', undefined]]).forEach(logMapElements)
// logs:
// "map.get('foo') = 3"
// "map.get('bar') = [object Object]"
// "map.get('baz') = undefined"
Copy the code

Set

It can be used to store any unique element, and the equality of two elements is consistent with the Map judgment method.

The constructor

new Set([iterable])
Copy the code

Instance properties and instance methods

This is the same as Map except for add (Map is a set method, set is add) and access (Map is get, set is not)

WeakMap

It is also a collection of key-value pairs, but the key can only be an object and the value is unlimited. The reference to a key object is a weak reference, that is, if there is no other reference to the object, the object is garbage collected and has the same API as Map. Another difference from Map is that its keys are not enumerable and you cannot get a list of keys (there are no clear and other iterative methods). Whether or not the key exists depends on whether or not it is recycled. If you want to add data to the object and do not want to interfere with garbage collection, you can use WeakMap a use scenario is to save private data for the object or hide Implementation Details, refer to Hiding Implementation Details with ECMAScript 6 WeakMaps

const privates = new WeakMap();

function Public() {
  const me = {
    // Private data goes here
  };
  privates.set(this, me);
}

Public.prototype.method = function () {
  const me = privates.get(this);
  // Do stuff with private data in `me`...
};

module.exports = Public;
Copy the code

In this way, the function’s private data and methods are stored in the private WeakMap, which can not be accessed by the outside module. Symbol can also achieve this effect. Of course, it can also be achieved through closures, but it will affect garbage collection

function Public() { const closedOverPrivate = "foo"; this.method = function () { // Do stuff with `closedOverPrivate`... }; } // Or function makePublic() { const closedOverPrivate = "foo"; return { method: function () { // Do stuff with `closedOverPrivate`... }}; }Copy the code

WeakSet

It is used to store weakly referenced objects (such as DOM objects) that are non-iterative and has three instance methods: Add, DELETE, and HAS.

24. Structured data

ArrayBuffer

Used to represent a general-purpose, fixed-length binary buffer, wherebufferBuffer refers to buffers, such as those for video playback, network data and local files.

It is a binary array that stores binary numbers. Instead of manipulating the contents directly, we need to create a TypedArray or DateView to read and write the contents of the buffer in a certain format.

The constructor

new ArrayBuffer(length)
Copy the code

Creates an arrayBuffer of a specified length, initialized to 1, up to the maximum safe number

  • ArrayBuffer. IsView (value) Checks whether the argument is an ArrayBuffer view

Instance attributes

  • Arraybuffer. byteLength Gets the length

Instance methods

  • Slice (begin[, end]) copies the specified location of the specified ArrayBuffer to a new arrayBuffer

SharedArrayBuffer

Similar to ArrayBuffer, but can be used to create views for shared memory and cannot be handled separately like ArrayBuffer. Different agents in the same cluster need to use postMessage and Structured cloning algorithm to share memory using SharedArrayBuffer. The latter accepts SharedArrayBuffers and TypedArrays that map to SharedArrayBuffers. In both cases, SharedArrayBuffers are passed to the recipient to generate a new private SharedArrayBuffers object, But both SharedArrayBuffers reference the same data block, and one changes the other

var sab = new SharedArrayBuffer(1024);
worker.postMessage(sab);
Copy the code

Synchronous operations on shared memory are required to use atomic operations. Contains an instance method slice (used to copy part of the content to generate another SharedArrayBuffer) and an instance property byteLength (which represents the length of bytes), as described in the Atomics section.

DataView

A low-level interface that reads and writes multiple numeric types from an ArrayBuffer object, regardless of the platform’s byte order.

Byte order

Endianness (endianness or byte-order) refers to how the computer arranges bytes to form numbers. Memory is stored in bytes (8 bits). More than one byte is needed to store numbers larger than 8 bits. Most scenarios use small byte order, that is, the highest byte order comes after, and the largest byte order is reversed, such as 0x12345678

  • The low byte order0x78 0x56 0x34 0x12
  • High byte order0x12 0x34 0x56 0x78

The constructor

new DataView(buffer [, byteOffset [, byteLength]])
Copy the code

A buffer refers to a buffer used to operate, such as an ArrayBuffer or SharedArrayBuffer, which returns a view.

Instance attributes

  • Dataview. buffer The buffer object referenced by dataView. buffer
  • Dataview. byteLength Length of a byte
  • Dataview. byteOffset Specifies the view’s offset from buffer

Instance methods

DataView objects can be accessed and manipulated by a number of methods. The access method contains one parameter, an offset value; The write method takes two parameters, the offset value and the value to be written. Different accessors are used to read and write different types of values, for example

// create an ArrayBuffer with a size in bytes
const buffer = new ArrayBuffer(16);

const view = new DataView(buffer);
view.setInt8(1, 127); // (max signed 8-bit integer)

console.log(view.getInt8(1));
// expected output: 127
Copy the code

Atomics

Atomic objects perform atomic operations on SharedArrayBuffer and ArrayBuffer with their static methods, similar to Math, which can only be used with their static methods, not instantiations

Atomic operation

When the content is shared, multiple threads can read and write the same data in memory, and atomic operations ensure predictability of value reads and writes without interruption until completion, when the next operation can proceed.

Wait and notify

Wait () and notify() use the Linux Futexes model (fast User-space Mutex) to make processes wait until a particular condition is true, primarily for blocking purposes. The thread is put to sleep by wait. Then wake up with Notify and don’t try to sleep the main thread. The memory used for the operation can only be Int32Array

  • Atomics.wait(typedArray, index, value[, timeout]) wait(typedArray, index, value[, timeout]) The return value is “OK “, “not-equal”, or “timed out”. The writing thread is notified when the specified location value changes
  • Atomics.notify(typedArray, index, count) Notifies a hibernating process after the specified location is changed

For example, hibernate in worker threads

//worker.js self.addEventListener('message', function (e) { const int32 = e.data console.log('You said: ' + int32); Atomics.wait(int32, 0, 0); console.log('........... ') }, false);Copy the code

Change in the main thread and then notify

//index.js var sab = new SharedArrayBuffer(1024); var int32 = new Int32Array(sab); console.log(int32[0]); const worker = new Worker('scripts/worker.js') console.log(worker) worker.postMessage(int32); setTimeout(() => { Atomics.store(int32, 0, 123); Atomics.notify(int32, 0, 1); }, 1500).Copy the code

A static method

Performs specific operations on the value at the typedArray specified location and the given value

  • Atomics.add(typedArray, index, Value) adds
  • Atomics.sub(typedArray, index, value) subtraction
  • Atomics.and(typedArray, index, value) and bit operation
  • Atomics.or(typedArray, index, value) or bit operation
  • Atomics.xor(typedArray, Index, Value) XOR bit operation
  • Atomics.compareExchange(typedArray, Index, expectedValue, replacementValue) If the expectedValue is equal to the current value, replace it with replacementValue, Otherwise unchanged
  • Atomics.exchange(typedArray, index, value) replaces the new value and returns the old value
  • Atomics.isLockFree(size) Determines whether a given size can be locked or atomized
Int8Array.BYTES_PER_ELEMENT; // 1 Uint8Array.BYTES_PER_ELEMENT; // 1 Uint8ClampedArray.BYTES_PER_ELEMENT; // 1 Int16Array.BYTES_PER_ELEMENT; // 2 Uint16Array.BYTES_PER_ELEMENT; // 2 Int32Array.BYTES_PER_ELEMENT; // 4 Uint32Array.BYTES_PER_ELEMENT; // 4 Float32Array.BYTES_PER_ELEMENT; // 4 Float64Array.BYTES_PER_ELEMENT; / / 8Copy the code
  • Atomics.load(typedArray, index) gets the value at the specified location
  • Atomics.store(typedArray, index, value) Saves the value at the specified location and returns the new value

JSON

This section focuses on three topics: an introduction to JSON and two static methods on JSON objects

JSON is introduced

JSON (JavaScript Object Notation) is a lightweight data interchange format for serializing objects, arrays, numbers, strings, booleans, and NULL. It is based on the JS syntax but is different, including the following

  • For objects and arrays, use double quotation marks for property names
  • Numbers, not starting with 0, followed by at least one digit if there is a decimal point, NaN and infinity are not supported
  • Any JSON text is a valid JS expression

JSON.parse(text[, reviver])

The optional reviver function is used to transform the string into a JSON object before returning. The reviver function is called from the inside out for the parsed value and all attributes it contains. This is the object to which the current attribute belongs, and the current attribute name and value are passed in as the first and second arguments. If undefined is returned, the current property will be deleted, and if another value is returned, the new value will be the property. When the top-level and last call is made, the property name is an empty string, as in

JSON.parse('{"p": 5}', function (k, v) { if(k === '') return v; Return v * 2; return v * 2; // Otherwise double the value of the property. }); // { p: 10 } JSON.parse('{"1": 1, "2": 2,"3": {"4": 4, "5": {"6": 6}}}', function (k, v) { console.log(k); // Output the current property name, so that the order of traversal is from inside out, // the last property name will be an empty string. return v; // Return the original attribute value, equivalent to no reviver argument passed. }); // 1/2/4/6 // 5/3 // ""Copy the code

JSON.stringify(value[, replacer[, space]])

Convert an object or value to a JSON string. Error if it contains a circular reference or bigInt. The replacer argument can be a function or an array.

When used as a function, there are two arguments: the key and value of the stringed object, where this is the object to which the key belongs. This function is called first by the object with the empty string as key, and then by each actual object, returning the following value

  • If the return is number, string, Boolean, null will be returned directly
  • If the Function, Symbol, undefined, change attributes will be ignored (returns undefined for array will be converted to null)
  • The replacer function is recursively called if other objects are returned
function replacer(key, value) {
  // Filtering out properties
  if (typeof value === 'string') {
    return undefined;
  }
  return value;
}

var foo = {foundation: 'Mozilla', model: 'box', week: 45, transport: 'car', month: 7};
JSON.stringify(foo, replacer);
// '{"week":45,"month":7}'
Copy the code

When used as an array, the values contained in the array are included in the result

JSON.stringify(foo, ['week', 'month']);
// '{"week":45,"month":7}', only keep "week" and "month" properties
Copy the code

The space argument controls the number of Spaces or values to indent the return value. It can be a string or a number. When it is a string, the indent is replaced by a string

JSON. Stringify ({2} a:, null, 'ee') / / results "{2} ee" a ":"Copy the code

When used as a number, the indent is the corresponding number of Spaces, up to 10

Stringing process

Follow these steps when stringing value

  • If value has a toJSON method (including a method in a nested object), it is returned as defined. The argument to this method is
    • If the object is an attribute value, the parameter is the attribute name
    • If it is an array, the array number is used as a string
    • An empty string if called directly on this object
var obj = { data: 'data', toJSON (key) { if (key) return `Now I am a nested object under key '${key}'`; else return this; }}; JSON.stringify(obj); // '{"data":"data"}', called directly on the object, key is empty string json.stringify ({obj}); // dictate property names (ES2015). // '{"obj":"Now I am a nested object under key 'obj'"}' // object as property json.stringify ([  obj ]); // '["Now I am a nested object under key '0'"]' // Object as an array elementCopy the code
  • Booleans, numbers, and string objects are converted to their corresponding raw values
  • Invalid values such as undefined,function, and symbol are ignored in objects and null in arrays
  • Attribute names given by symbol are ignored
  • Date instances are treated as strings because they implement toJSON that returns strings (equivalent to date.toisostring ())
  • Enumerable properties of other objects are serialized

25. Memory management

This paper is divided into three parts, overview and introduction of two related objects WeakRef and FinalizationRegistry

An overview of the

There is no manual way to manage memory in JS. Instead, memory is allocated when objects are created and garbage collection is released when they are no longer used.

Memory life cycle

The memory life cycle of each language is the same, divided into allocating memory, reading and writing memory, freeing memory.

  • Memory allocation in js
    • The initialization of a value is automatically allocated when the value initialization is declared
    var n = 123; // Allocate memory for a number var s = 'AZERty '; Var o = {a: 1, b: null}; Var a = [1, null, 'abra']; var a = [1, null, 'abra']; function f(a) { return a + 2; } // Allocate memory for function objectsCopy the code
    • Allocate memory through function calls
    var d = new Date(); Var e = document.createElement('div'); // Assign a DOM element // There are other methods, such as substr var s = 'AZERty '; var s2 = s.substr(0, 3);Copy the code
  • Using values is reading and writing from allocated memory
  • Free memory when it is no longer needed. Memory management problems occur primarily in this phase, where the most difficult part is determining when allocated memory is no longer needed. Low-level languages (such as C) require the user to manually indicate when allocated memory is no longer needed and to release it. High-level languages like JS use a form of memory management called garbage Collection (GC) to monitor memory allocation and determine when to free it. This treatment is an approximation because it is difficult to calculate directly.

garbage collection

To understand garbage collection, understand a few concepts

  • References are the main concept of garbage collection algorithms. If an object can access (explicitly or implicitly) another object, it is called a reference to another object. For example, an object implicitly references its [[prototype]] and directly references its properties
  • Reference-counting is used in the original garbage collection algorithm. This algorithm simplifies whether an object is used to whether there are other object references. If an object has no other object references, it is called garbage
Var x = {a: {b: 2}}; var x = {b: 2}}; // the y variable is the second reference to the outer layer object. // now x is assigned to 1, and the outer object reference is y x = 1; Var z = y.a; // The inner object is assigned to z, and the inner object has two references. // Now the reference to the outer object becomes 0 and is garbage collected, but the inner object is referenced by z and cannot be garbage collected y = 'mozilla'; // The reference to the inner object also becomes a garbage collector z = null;Copy the code

One limitation of this approach is circular references. In the following example, two objects are circular references. They are no longer needed when the function call ends, but circular references are a common cause of memory leaks because the number of references cannot be reclaimed

function f() {
  var x = {};
  var y = {};
  x.a = y;        // x references y
  y.a = x;        // y references x

  return 'azerty';
}

f();
Copy the code
  • Mark-and-sweep algorithm, which eliminates the need for objects to be reduced to an object being unreachable. This algorithm assumes that there is an object called root, which in JS is a global object. The garbage collector periodically finds all referenced (directly or indirectly) objects, starting with the root object, and then finds unreachable objects for garbage collection. A 0 reference is also effectively unreachable, and a circular reference can also be handled effectively. In 2012 all browsers used the tag clearing algorithm.

WeakRef

A WeakRef object contains a weak reference to another object, which is called target or referent. A weak reference to an object does not prevent the object from being garbage collected, and a corresponding strong or normal reference is kept in memory. Different JS engines have different implementations of garbage collection and should be used with caution

The constructor

new WeakRef(targetObject);
Copy the code

Arguments are weakly referenced objects

Instance methods

  • Obj = ref.deref() returns the referenced object, or undefined if reclaimed

FinalizationRegistry

A callback is executed when a registered object is cleaned up

The constructor

new FinalizationRegistry([callback]);
Copy the code

Create an object using the callback argument

Instance methods

Contains register and unregister instance methods for registering and unregistering, respectively

  • Registry. register(target, heldValue, [unregisterToken]) where target is the registered object, heldValue is the parameter passed to the callback, and unregisterToken is the token used to cancel registration
const registry = new FinalizationRegistry(heldValue => {
  // ....
});
registry.register(theObject, "some value",unregisterToken);
registry.unregister(unregisterToken);
Copy the code

26. Control abstract objects

Can be used to structure code, especially asynchronous code, such as not requiring deep nesting

Iteration

Iteration is not a built-in object or a new syntax. Instead, Iteration is a protocol that can be implemented by any object following certain conventions. These include the following two agreements

Iterable protocol

The Iterable Protocol allows javascript objects to customize The iterative behavior for… In and so on. Array and so on are built-in iterable, Object is not. To be iterable, an object implements the @@iterator method, which means that the object must have the @@iterator property, which is accessed using the symbol. iterator constant. This method takes no arguments when called and returns an iterator.

Iterator protocol

The Iterator Protocol defines a standard way to produce a series of values. It is an iterator when an object implements the next() method in the following semantics. Next () is a no-argument function that returns an object that should have the following two properties

  • Done Boolean, false if the iterator can produce the next value, true otherwise, the next value is optional
  • Value Any type

Such as

var myIterable = {}; myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; }; [...myIterable]; / / [1, 2, 3]Copy the code

Promise

A promise is a proxy of values that are not necessarily known at the time of creation, and can be used to associate the success value and failure reason of an asynchronous operation with the associated processing. This allows asynchronous methods to return a value like synchronous methods, but not an end value but a promise that will provide a value at some future time. A promise can be in one of three states

  • Pending indicates the initial state, neither fullfilled nor Rejected
  • A big pity means the successful completion of an operation
  • Rejected indicates that the operation fails

A pending promise is either fulfilled or rejected. When they happen, the related handlers queued with the THEN method will be executed. Because the then and catch methods return a promise, they can be called chained

The constructor

Used to wrap a function that returns a value other than a promise

new Promise(executor)
Copy the code

The Executor function is executed during the instantiation process. It contains resolve and reject. Asynchronous operations can be performed with resolve if the operation succeeds, reject if it fails, and reject if the Executor fails.

const myFirstPromise = new Promise((resolve, reject) => {
  // do something asynchronous which eventually calls either:
  //
  //   resolve(someValue)        // fulfilled
  // or
  //   reject("failure reason")  // rejected
});
Copy the code

A static method

  • The promise.all (iterable) argument is an iterated object used to collectively process the return results of multiple promises. The return value is
    • If the argument is empty, the return value is an Resolved promise and the success value is empty
    • If the iterator does not contain a promise, an Resolved Promise is returned with the success value as an array of the iterator elements
    • The other case is a pending promise. As long as there is a promise rejected in the iterator, it will be rejected, or all resolved will be resolved.
  • Promise.allsettled (iterable) is also used to handle the return result of multiple promises.Whether a Promise succeeds or fails in an iterator will be returned together at the end
Promise.allSettled([
  Promise.resolve(33),
  new Promise(resolve => setTimeout(() => resolve(66), 0)),
  99,
  Promise.reject(new Error('an error'))
])
.then(values => console.log(values));

// [
//   {status: "fulfilled", value: 33},
//   {status: "fulfilled", value: 66},
//   {status: "fulfilled", value: 99},
//   {status: "rejected",  reason: Error: an error}
// ]
Copy the code
  • Promise.any(iterable) is the opposite of the all method, where one success is returned and all failures are considered failures
  • Promise.race(iterable) takes the first Promise that returns the result
  • Promise.reject(reason) Returns a Promise with the argument reason rejected
  • Promise.resolve(value) returns a resolved Promise with parameter values

Instance methods

  • The p.match (onRejected) argument is called when P is rejected, and the argument is the reason. This method returns a promise. When the callback returns a reject promise or throw error, the promise returned by. Catch will be Rejected or resolved
  • This is a big pity (onFulfilled[, onRejected])
  • P.f, of (onFinally), will the callback function be called no matter what the result

Generator

Generator objects are returned by calling Generator functions, following the iterable and iterator protocols

function* generator() { yield 1; yield 2; yield 3; } const gen = generator(); // "Generator { }" console.log(gen.next().value); // 1 console.log(generator().next().value); // 1 console.log(generator().next().value); / / 1Copy the code

Generator function

Generator functions are used to generate iterators. Written using function* syntax, the initial call returns an iterator, and the generator function is executed by calling the next method on the iterator until the yield keyword is reached. Each call returns a new iterator, and each iterator can only be iterated once. The yield syntax used to suspend execution of a generator function is

[rv] = yield [expression];
Copy the code

The value of the expression after yield is returned to the caller of the generator. Yield returns an object containing both value (value refers to the expression above) and done (done is a Boolean value indicating whether the generator has completed execution). Rv refers to the argument passed when the iterator next method is called, for example

function* counter(value) { let step; while (true) { step = yield ++value; if (step) { value += step; } } } const generatorFunc = counter(0); console.log(generatorFunc.next().value); // 1 console.log(generatorFunc.next().value); // 2 console.log(generatorFunc.next().value); // 3 console.log(generatorFunc.next(10).value); // 14 console.log(generatorFunc.next().value); // 15 console.log(generatorFunc.next(10).value); / / 26Copy the code

Instance methods

  • Gen. Next (value) returns the yield object, and the value argument is assigned to the RV as the actual yield return value
  • Gen. return(value) Returns the givenvalue, and terminates the iterator, returning {value:value, done: true }
  • Gen. throw(exception) throws an error, used for debugging

GeneratorFunction

Constructor of generator functions, using reference generator functions

new GeneratorFunction ([arg1[, arg2[, ...argN]],] functionBody)
Copy the code

AsyncFunction

Constructor of async function

new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody)
Copy the code

Here’s an example of how to use an asynchronous function expansion. Async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async: async Catch caught.

// async function name([param[, param[,...param]]]) {statements} yield keyword [rv] = await expression;Copy the code

27.

Reflect

The Reflect object provides methods for intercepting JS operations, the same as proxy Handlers, but note that we are using its static methods. The methods involved partly overlap on Object, so refer to Comparing Reflect and Object methods for details

A static method

  • Reflect.apply(target, thisArgument, argumentsList) similar to function.prototype.apply ()
  • Reflect.construct(target, argumentsList[, newTarget]) similar to new target(… args)
  • Reflect.defineproperty (target, propertyKey, attributes) similar to Object.defineProperty()
  • Reflect.deleteproperty (target, propertyKey) similar to delete target[name]
  • Reflect.get(target, propertyKey[, receiver]) similar to target[name]
  • Reflect. GetOwnPropertyDescriptor (target, propertyKey) similar to the Object. The getOwnPropertyDescriptor ()
  • Reflect the getPrototypeOf similar Object (target). GetPrototypeOf ()
  • Reflect.has(target, propertyKey) is similar to the in operator
  • Reflect the isExtensible similar Object (target). IsExtensible ()
  • Reflect.ownkeys (target) is similar to object.keys () but not affected by enumerable attributes
  • Reflect the preventExtensions similar Object (target). PreventExtensions ()
  • Reflect.set(target, propertyKey, value[, receiver]) similar property accessor syntax
  • Reflect.setprototypeof (target, prototype) similar to Object.setprototypeof ()

Proxy

A proxy used to create an object that intercepts and customizes operations on the object

const p = new Proxy(target, handler)
Copy the code

Where target is the propped object and handler is a proxy callback to various operations, where handler’s key-value pairs are Reflect’s various static methods, for example

const target = {
  notProxied: "original value",
  proxied: "original value"
};

const handler = {
  get: function(target, prop, receiver) {
    if (prop === "proxied") {
      return "replaced value";
    }
    return Reflect.get(...arguments);
  }
};

const proxy = new Proxy(target, handler);

console.log(proxy.notProxied); // "original value"
console.log(proxy.proxied);    // "replaced value"
Copy the code

28. Memory model

The memory consistency Model, or memory model, specifies The sequence of events for shared data blocks, These events are generated through TypedArray instance access and Atomics objects supported by SharedArrayBuffer. In the absence of a data race, the order of operations on the same block of memory (in different environments) is guaranteed to be the same, but in the presence of a Date race, the actual execution is different from the expected due to compiler conversion and CPU design. The memory model is the solution to this scenario.

There is little information about THE JS Memory Consistency model, so I cannot read too much here. For the time being, I will refer to the Consistency Model and Memory Consistency Models: A Tutorial to learn something about the Memory Consistency model.

conclusion

By now the ECMAscript specs have gone through, so you can either check for gaps or read the following content.