Guten Tag, Freunde!
Dieser Artikel konzentriert sich auf die JavaScript-Funktionen , die in der neuen Version der Spezifikation (ECMAScript 2021, ES12) vorgestellt werden.
Es wird um Folgendes gehen:
- String.prototype.replaceAll ()
- Promise.any ()
- Schwache Riffe
- Boolesche Zuweisungsoperatoren
- Zahlentrennzeichen
String.prototype.replaceAll ()
Mit String.prototype.replaceAll () ( Mathias Bynens-Klausel ) können Sie alle Instanzen eines Teilstrings in einem String durch einen anderen Wert ersetzen, ohne einen globalen regulären Ausdruck zu verwenden.
Im folgenden Beispiel ersetzen wir alle "+" - Zeichen durch Kommas durch ein Leerzeichen mit einem regulären Ausdruck:
const strWithPlus = '++'
const strWithComma = strWithPlus.replace(/+/g, ', ')
// , ,
Dieser Ansatz erfordert die Verwendung eines regulären Ausdrucks. Komplexe reguläre Ausdrücke sind jedoch häufig eine Fehlerquelle.
Es gibt einen anderen Ansatz, der auf der Verwendung der Methoden String.prototype.split () und Array.prototype.join () basiert:
const strWithPlus = '++'
const strWithComma = strWithPlus.split('+').join(', ')
// , ,
Bei diesem Ansatz wird die Verwendung regulärer Ausdrücke vermieden. Sie müssen die Zeichenfolge jedoch in separate Teile (Wörter) aufteilen, in ein Array konvertieren und die Array-Elemente dann in eine neue Zeichenfolge verketten.
String.prototype.replaceAll () löst diese Probleme und bietet eine einfache und bequeme Möglichkeit, Teilzeichenfolgen global zu ersetzen:
const strWithPlus = '++'
const strWithComma = strWithPlus.replaceAll('+', ', ')
// , ,
Beachten Sie, dass aus Gründen der Konsistenz mit früheren APIs das Verhalten von String.prototype.replaceAll (searchValue, newValue) (searchValue ist der Suchwert, newValue ist der neue Wert) mit String.prototype.replace (searchValue, newValue) identisch ist, mit Ausnahme der folgenden:
- Wenn der gesuchte Wert eine Zeichenfolge ist, ersetzt replaceAll alle Übereinstimmungen und nur die erste
- Wenn der gewünschte Wert ein nicht globaler regulärer Ausdruck ist, ersetzt Ersetzen die erste Übereinstimmung, und replaceAll löst eine Ausnahme aus, um einen Konflikt zwischen dem Fehlen des Flags "g" und dem Methodennamen zu vermeiden (alle ersetzen - alle ersetzen [Übereinstimmungen]).
Wenn ein globaler regulärer Ausdruck als Suchwert verwendet wird, verhalten sich replace und replaceAll gleich.
Was ist, wenn wir am Anfang, am Ende der Zeile und zwischen Wörtern eine Zeile mit einer beliebigen Anzahl von Leerzeichen haben?
const whiteSpaceHell = ' '
Und wir wollen zwei oder mehr Leerzeichen durch ein Leerzeichen ersetzen. Kann replaceAll dieses Problem lösen? Nein.
Mit String.prototype.trim () und Ersetzen durch einen globalen regulären Ausdruck geschieht dies folgendermaßen:
const whiteSpaceNormal =
whiteSpaceHell
.trim()
.replace(/\s{2,}/g, ' ')
// \s{2,}
//
Promise.any ()
Promise.any () (ein Vorschlag von Mathias Bynens, Kevin Gibbons und Sergey Rubanov ) gibt den Wert des ersten erfüllten Versprechens zurück. Wenn alle Versprechen, die als Argument (als Array) an Promise.any () übergeben wurden, abgelehnt werden, wird eine "AggregateError" -Ausnahme ausgelöst.
AggregateError ist eine neue Fehlerunterklasse, die einzelne Fehler gruppiert. Jede AggregateError-Instanz enthält einen Verweis auf ein Array mit Ausnahmen.
Betrachten wir ein Beispiel:
const promise1 = new Promise((resolve, reject) => {
const timer = setTimeout(() => {
resolve('p1')
clearTimeout(timer)
}, ~~(Math.random() * 100))
}) // ~~ - Math.floor()
const promise2 = new Promise((resolve, reject) => {
const timer = setTimeout(() => {
resolve('p2')
clearTimeout(timer)
}, ~~(Math.random() * 100))
})
;(async() => {
const result = await Promise.any([promise1, promise2])
console.log(result) // p1 p2
})()
Das Ergebnis ist der Wert des ersten aufgelösten Versprechens.
Beispiel aus dem Satz:
Promise.any([
fetch('https://v8.dev/').then(() => 'home'),
fetch('https://v8.dev/blog').then(() => 'blog'),
fetch('https://v8.dev/docs').then(() => 'docs')
]).then((first) => {
// ()
console.log(first);
// → 'home'
}).catch((error) => {
//
console.log(error);
})
Beachten Sie, dass Promise.race () im Gegensatz zu Promise.any () den Wert des ersten aufgelösten Versprechens zurückgibt, unabhängig davon, ob es erfüllt oder abgelehnt wurde.
Schwache Riffe
WeakRefs (schwache Referenzen) ( vorgeschlagen von Dean Tribble, Mark Miller, Till Schneidereit usw. ) bietet zwei neue Funktionen:
- Erstellen schwacher Verweise auf ein Objekt mithilfe der WeakRef-Klasse
- Ausführen benutzerdefinierter Finalizer nach der Garbage Collection mit der FinalizationRegistry-Klasse
Kurz gesagt, mit WeakRef können Sie schwache Verweise auf Objekte erstellen, die die Werte von Eigenschaften eines anderen Objekts sind, und Finalizer können unter anderem verwendet werden, um Verweise auf Objekte zu entfernen, die vom Garbage Collector "bereinigt" wurden.
Diese Technik kann nützlich sein, wenn eine Speicherfunktion (Memoization) erstellt wird, die den integrierten Cache verwendet, um die wiederholte Ausführung der Funktion zu verhindern, wenn ein berechneter Wert für das an die Funktion im Cache übergebene Argument vorhanden ist (vorausgesetzt, Objekte werden als Werte für die Eigenschaften des Cache-Objekts verwendet und das Risiko ihres späteren Löschens). ...
Wie Sie sich erinnern, war der Grund für das Auftreten einer solchen Struktur wie Map (Hash-Tabelle) in JavaScript neben der schnelleren Suche nach einem Wert nach Schlüssel, dass die Schlüssel eines normalen Objekts nur Zeichenfolgen oder Zeichen sein können. Map hingegen ermöglicht die Verwendung eines beliebigen Datentyps als Schlüssel, einschließlich Objekte.
Es trat jedoch bald ein Problem mit Speicherverlusten auf: Durch das Löschen von Objekten, bei denen es sich um Map-Schlüssel handelte, waren diese Objekte nicht unerreichbar (Mark-and-Sweep), wodurch der Garbage Collector daran gehindert wurde, sie zu zerstören und den von ihnen belegten Speicher freizugeben.
Mit anderen Worten, die als Schlüssel in der Karte verwendeten Objekte werden für immer gespeichert.
Um dieses Problem zu lösen, wurde eine andere Struktur eingeführt - WeakMap (und WeakSet). Der Unterschied zwischen WeakMap und Map besteht darin, dass Verweise auf Schlüsselobjekte in WeakMap schwach sind: Durch das Löschen solcher Objekte kann der Garbage Collector den ihnen zugewiesenen Speicher neu zuweisen.
Somit stellt dieser Vorschlag die nächste Stufe bei der Entwicklung einer Hash-Tabelle in JavaScript dar. Objekte können jetzt sowohl als Schlüssel als auch als Werte in anderen Objekten verwendet werden, ohne dass das Risiko von Speicherverlusten besteht.
Noch einmal, wenn es darum geht, einen Inline-Cache zu erstellen:
- Wenn keine Gefahr von Speicherlecks besteht, verwenden Sie Map
- Verwenden Sie WeakMap, wenn Sie Schlüsselobjekte verwenden, die anschließend gelöscht werden können
- Wenn Sie Wertobjekte verwenden, die später entfernt werden können, verwenden Sie Map in Verbindung mit WeakRef
Ein Beispiel für den letzten Fall aus dem Vorschlag:
function makeWeakCached(f) {
const cache = new Map()
return key => {
const ref = cache.get(key)
if (ref) {
//
const cached = ref.deref()
if (cached !== undefined) return cached;
}
const fresh = f(key)
// ( )
cache.set(key, new WeakRef(fresh))
return fresh
};
}
const getImageCached = makeWeakCached(getImage);
- Der WeakRef-Konstruktor verwendet ein Argument, das ein Objekt sein muss, und gibt einen schwachen Verweis darauf zurück
- Die deref-Methode einer WeakRef-Instanz gibt einen von zwei Werten zurück:
Im Fall des eingebauten Caches ist der Finalizer so konzipiert, dass er den Bereinigungsprozess abschließt, nachdem das Wertobjekt vom Garbage Collector zerstört wurde, oder einfacher gesagt, einen schwachen Verweis auf ein solches Objekt entfernt.
function makeWeakCached(f) {
const cache = new Map()
// -
const cleanup = new FinalizationRegistry(key => {
const ref = cache.get(key)
if (ref && !ref.deref()) cache.delete(key)
})
return key => {
const ref = cache.get(key)
if (ref) {
const cached = ref.deref()
if (cached !== undefined) return cached
}
const fresh = f(key)
cache.set(key, new WeakRef(fresh))
// ( )
cleanup.register(fresh, key)
return fresh
}
}
const getImageCached = makeWeakCached(getImage);
Lesen Sie mehr über Finalizer und deren Verwendung im Vorschlag. Verwenden Sie Finalizer im Allgemeinen nur, wenn dies unbedingt erforderlich ist.
Boolesche Zuweisungsoperatoren
Boolesche Zuweisungsoperatoren ( Justin Ridgewells Vorschlag und Hemanth HM ) sind eine Kombination aus Booleschen Operatoren (&&, ||, ??) und Zuweisungsausdrücken.
Bis heute verfügt JavaScript über die folgenden Zuweisungsoperatoren:
=
+=
-=
/=
*=
&&=
||=
??=
(null undefined - , 0, false, '' - )
**=
%=
&=
|=
^=
<<=
>>=
>>>=
[a, b] = [ 10, 20 ]
{a, b} = { a: 10, b: 20 }
Mit dieser Klausel können Sie logische Operatoren und Zuweisungsausdrücke kombinieren:
a ||= b
// : a || (a = b)
// , "a"
a &&= b
// : a && (a = b)
// , "a"
a ??= b
// : a ?? (a = b)
// , "a" (null undefined)
Beispiel aus einem Satz:
//
function example(opts) {
// ,
opts.foo = opts.foo ?? 'bar'
// ,
opts.baz ?? (opts.baz = 'qux')
}
example({ foo: 'foo' })
//
function example(opts) {
//
opts.foo ??= 'bar'
// "" opts.baz
opts.baz ??= 'qux';
}
example({ foo: 'foo' })
Zahlentrennzeichen
Mit Zahlentrennzeichen ( Christophe Porteneuves Vorschlag ), genauer gesagt mit Zahlentrennzeichen in Zahlen, können Sie einen Unterstrich (_) zwischen Zahlen einfügen , um die Lesbarkeit von Zahlen zu verbessern.
Zum Beispiel:
const num = 100000000
// num? 1 ? 100 ? 10 ?
Separatoren lösen dieses Problem:
const num = 100_000_000 // : 100
Trennzeichen können sowohl im Ganzzahl- als auch im Dezimalteil einer Zahl verwendet werden:
const num = 1_000_000.123_456
Trennzeichen können nicht nur in Ganzzahlen und Gleitkommazahlen verwendet werden, sondern auch in binären, hexadezimalen, oktalen und BigInt-Literalen.
Die Weiterentwicklung von Zahlentrennzeichen impliziert die Möglichkeit der nützlichen Verwendung mehrerer aufeinanderfolgender Trennzeichen und Trennzeichen, die vor und nach der Zahl stehen.
Möchten Sie Ihre JavaScript-Kenntnisse testen oder auffrischen? Dann achten Sie auf meine wunderbare Bewerbung (Sie können sich nicht selbst loben ...).
Ich hoffe, Sie haben etwas Interessantes für sich gefunden. Vielen Dank für Ihre Aufmerksamkeit.