Bonne journée, mes amis!
Cet article se concentre sur les fonctionnalités JavaScript qui seront présentées dans la nouvelle version de la spécification (ECMAScript 2021, ES12).
Il s'agira de ce qui suit:
- String.prototype.replaceAll ()
- Promise.any ()
- WeakRefs
- Opérateurs d'affectation booléens
- Séparateurs de nombres
String.prototype.replaceAll ()
String.prototype.replaceAll () ( clause Mathias Bynens ) vous permet de remplacer toutes les instances d'une sous-chaîne dans une chaîne par une valeur différente sans utiliser une expression régulière globale.
Dans l'exemple suivant, nous remplaçons tous les caractères "+" par des virgules par un espace à l'aide d'une expression régulière:
const strWithPlus = '++'
const strWithComma = strWithPlus.replace(/+/g, ', ')
// , ,
Cette approche nécessite l'utilisation d'une expression régulière. Cependant, les expressions régulières complexes sont souvent une source d'erreurs.
Il existe une autre approche basée sur l'utilisation des méthodes String.prototype.split () et Array.prototype.join ():
const strWithPlus = '++'
const strWithComma = strWithPlus.split('+').join(', ')
// , ,
Cette approche évite l'utilisation d'expressions régulières, mais vous devez diviser la chaîne en parties séparées (mots), la convertir en tableau, puis concaténer les éléments du tableau en une nouvelle chaîne.
String.prototype.replaceAll () résout ces problèmes et fournit un moyen simple et pratique de remplacer globalement les sous-chaînes:
const strWithPlus = '++'
const strWithComma = strWithPlus.replaceAll('+', ', ')
// , ,
Notez que pour maintenir la cohérence avec les API précédentes, le comportement de String.prototype.replaceAll (searchValue, newValue) (searchValue est la valeur de recherche, newValue est la nouvelle valeur) est le même que String.prototype.replace (searchValue, newValue), sauf pour ce qui suit:
- Si la valeur recherchée est une chaîne, replaceAll remplace toutes les correspondances et remplace uniquement la première
- Si la valeur souhaitée est une expression régulière non globale, alors replace remplace la première correspondance et replaceAll lève une exception pour éviter un conflit entre l'absence de l'indicateur «g» et le nom de la méthode (remplacer tout - remplacer tous [correspondances])
Si une expression régulière globale est utilisée comme valeur de recherche, alors replace et replaceAll se comportent de la même manière.
Et si nous avons une ligne avec un nombre arbitraire d'espaces au début, à la fin de la ligne et entre les mots?
const whiteSpaceHell = ' '
Et nous voulons remplacer deux ou plusieurs espaces par un seul. ReplaceAll peut-il résoudre ce problème? Non.
Avec String.prototype.trim () et remplacez par une expression régulière globale, cela se fait comme ceci:
const whiteSpaceNormal =
whiteSpaceHell
.trim()
.replace(/\s{2,}/g, ' ')
// \s{2,}
//
Promise.any ()
Promise.any () (une suggestion de Mathias Bynens, Kevin Gibbons et Sergey Rubanov ) renvoie la valeur de la première promesse tenue. Rejeter toutes les promesses passées à Promise.any () en tant qu'argument (en tant que tableau) lève une exception "AggregateError".
AggregateError est une nouvelle sous-classe d'erreur qui regroupe des erreurs individuelles. Chaque instance AggregateError contient une référence à un tableau avec des exceptions.
Prenons un exemple:
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
})()
Le résultat sera la valeur de la première promesse résolue.
Exemple de la phrase:
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);
})
Notez que Promise.race (), contrairement à Promise.any (), renvoie la valeur de la première promesse résolue, qu'elle soit remplie ou rejetée.
WeakRefs
WeakRefs (références faibles) ( proposé par Dean Tribble, Mark Miller, Till Schneidereit, etc. ) propose deux nouvelles fonctionnalités:
- Création de références faibles à un objet à l'aide de la classe WeakRef
- Exécution de finaliseurs personnalisés après le garbage collection à l'aide de la classe FinalizationRegistry
En bref, WeakRef vous permet de créer des références faibles à des objets qui sont les valeurs des propriétés d'un autre objet, et les finaliseurs peuvent être utilisés, entre autres, pour supprimer les références aux objets «nettoyés» par le garbage collector.
Cette technique peut être utile lors de la création d'une fonction de mémorisation (mémorisation) qui utilise le cache intégré pour empêcher l'exécution répétée de la fonction s'il y a une valeur calculée pour l'argument passé à la fonction dans le cache (à condition que les objets soient utilisés comme valeurs des propriétés de l'objet du cache et le risque de leur suppression ultérieure) ...
Comme vous vous en souvenez, la raison de l'apparition en JavaScript d'une structure telle que Map (table de hachage), en plus de la recherche plus rapide d'une valeur par clé, était que les clés d'un objet ordinaire ne peuvent être que des chaînes ou des caractères. Map, d'autre part, vous permet d'utiliser n'importe quel type de données comme clé, y compris les objets.
Cependant, un problème de fuite de mémoire est rapidement apparu: la suppression d'objets qui étaient des clés de carte ne rendait pas ces objets inaccessibles (marquer et balayer), ce qui empêchait le garbage collector de les détruire, libérant ainsi la mémoire qu'ils occupaient.
En d'autres termes, les objets utilisés comme clés dans la carte sont enregistrés pour toujours.
Une autre structure, WeakMap (et WeakSet), a été introduite pour résoudre ce problème. La différence entre WeakMap et Map est que les références aux objets clés dans WeakMap sont faibles: la suppression de ces objets permet au garbage collector de réallouer la mémoire qui leur est allouée.
Ainsi, cette proposition représente la prochaine étape dans le développement d'une table de hachage en JavaScript. Les objets peuvent désormais être utilisés à la fois comme clés et comme valeurs dans d'autres objets sans risque de fuite de mémoire.
Encore une fois, quand il s'agit de créer un cache en ligne:
- S'il n'y a aucun risque de fuite de mémoire, utilisez Map
- Lorsque vous utilisez des objets clés pouvant être supprimés ultérieurement, utilisez WeakMap
- Lorsque vous utilisez des objets de valeur pouvant être supprimés ultérieurement, utilisez Map en conjonction avec WeakRef
Un exemple du dernier cas de la proposition:
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);
- Le constructeur WeakRef prend un argument qui doit être un objet et lui renvoie une référence faible
- La méthode deref d'une instance WeakRef renvoie l'une des deux valeurs suivantes:
Dans le cas du cache intégré, le finaliseur est conçu pour terminer le processus de nettoyage après la destruction de l'objet de valeur par le garbage collector, ou, plus simplement, pour supprimer une référence faible à un tel objet.
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);
En savoir plus sur les finaliseurs et comment les utiliser dans la proposition. En général, n'utilisez les finaliseurs que lorsque cela est absolument nécessaire.
Opérateurs d'affectation booléens
Les opérateurs d'affectation booléens ( proposition de Justin Ridgewell et Hemanth HM ) sont une combinaison d'opérateurs booléens (&&, ||, ??) et d'expressions d'affectation.
À partir d'aujourd'hui, JavaScript possède les opérateurs d'affectation suivants:
=
+=
-=
/=
*=
&&=
||=
??=
(null undefined - , 0, false, '' - )
**=
%=
&=
|=
^=
<<=
>>=
>>>=
[a, b] = [ 10, 20 ]
{a, b} = { a: 10, b: 20 }
La clause vous permet de combiner des opérateurs logiques et des expressions d'affectation:
a ||= b
// : a || (a = b)
// , "a"
a &&= b
// : a && (a = b)
// , "a"
a ??= b
// : a ?? (a = b)
// , "a" (null undefined)
Exemple d'une phrase:
//
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' })
Séparateurs de nombres
Les séparateurs de nombres ( suggestion de Christophe Porteneuve ), ou plus précisément les séparateurs de nombres dans les nombres, permettent d'ajouter un trait de soulignement (_) entre les nombres pour rendre les nombres plus lisibles.
Par exemple:
const num = 100000000
// num? 1 ? 100 ? 10 ?
Les séparateurs résolvent ce problème:
const num = 100_000_000 // : 100
Les séparateurs peuvent être utilisés à la fois dans les parties entières et décimales d'un nombre:
const num = 1_000_000.123_456
Les séparateurs peuvent être utilisés non seulement dans les entiers et les nombres à virgule flottante, mais aussi dans les littéraux binaires, hexadécimaux, octaux et BigInt.
Le développement ultérieur des séparateurs de nombres implique la possibilité d'utiliser utilement plusieurs séparateurs et séparateurs consécutifs qui viennent avant et après le nombre.
Vous cherchez à tester ou à rafraîchir vos connaissances JavaScript? Alors faites attention à ma merveilleuse application (vous ne pouvez pas vous féliciter ...).
J'espère que vous avez trouvé quelque chose d'intéressant pour vous-même. Merci de votre attention.