JavaScript >> Javascript-Tutorial >  >> Tags >> map

ES6, ES7, ES8 &Schreiben von modernem JavaScript Pt5 – WeakMap, WeakSet und Export &Import

ES6 hat JavaScript viele neue Funktionen gebracht. In diesem Teil lernen, verstehen und beherrschen Sie WeakMap , WeakSet und export und import Anweisungen, einschließlich dynamischer Importe. Sie werden auch etwas über schwache und starke Referenz lernen. Lernen Sie die Grundlagen von ES6 kennen und werden Sie ein besserer JavaScript-Entwickler!

ES6, ES7, ES8 &Modernes JavaScript schreiben Teil 1 (Scope, let, const, var).

ES6, ES7, ES8 &Schreiben von modernem JavaScript Teil 2 (Vorlagenliterale, Destrukturierung und Standardparameter).

ES6, ES7, ES8 &Schreiben von modernem JavaScript Teil 3 (Spread, Rest, Sets &Object Literal).

ES6, ES7, ES8 &Modernes JavaScript schreiben Teil 4 (Enthält Pads, Loops &Maps).

ES6, ES7, ES8 &Modernes JavaScript schreiben, Teil 6 (Pfeilfunktionen &Versprechen).

ES6, ES7, ES8 &Modernes JavaScript schreiben Teil 7 (Async/await &Klassen).

WeakMap und WeakSet

Im dritten Teil haben Sie Sets kennengelernt. Dann, im vierten Teil, haben Sie auch etwas über Karten gelernt. Seit der Veröffentlichung von ES6 haben diese beiden Objekte auch ihre „schwächeren“ Gegenstücke. Diese Gegenstücke heißen WeakMap und WeakSet . Dies wirft eine Frage auf. Was ist der Unterschied zwischen Map und WeakMap und Set und WeakSet ?

In dieser Situation wird das Wort „schwach“ verwendet, um einen Referenztyp oder einen Zeigertyp anzugeben. Im Fall von WeakMap es bedeutet, dass die Schlüssel/Wert-Paare innerhalb des WeakMap sind schwach referenziert sind (schwache Zeiger). Im Fall von WeakSet sie sind die Objekte innerhalb von WeakSet die schwach referenziert werden (schwache Zeiger). Was bedeutet es dennoch, wenn auf etwas schwach verwiesen wird?

Ein schwacher Verweis bedeutet, dass, wenn etwas aus dem Speicher entfernt wird und alle Verweise auf dieses Ding entfernt werden, das Ding selbst der Garbage Collection unterzogen werden kann. Wenn Sie also versuchen, auf dieses Ding zuzugreifen, erhalten Sie undefined weil es keine Hinweise darauf gibt. Dies gilt nicht für Dinge mit starkem Bezug. Sie werden nicht von der Garbage Collection erfasst, wenn kein anderer Verweis darauf vorhanden ist.

Eine andere Art, es auszudrücken. Ein schwach referenziertes Ding (ein jüngerer Bruder) wird nur dann vor der Garbage Collection (ein Tyrann) geschützt, wenn ein anderer Verweis darauf (ein älterer Bruder) existiert (nahe ist). Wenn alle Referenzen weg sind (der ältere Bruder ist woanders), ist das schwach referenzierte Ding (der jüngere Bruder) nicht länger vor der Garbage Collection (dem Mobber) geschützt und wird eingesammelt (wird gemobbt).

WeakMap

Lassen Sie uns dies an einem einfachen Beispiel demonstrieren. Im Beispiel unten initialisieren Sie zwei Variablen, mapExample und weakMapExample , mit Map und WeakMap . Danach fügen Sie eine weitere Variable objExample hinzu und initialisieren Sie es als Objekt mit einem Schlüssel und Wert. Dann verwenden Sie den objExample um ein neues Paar zu mapExample hinzuzufügen und weakMapExample .

Als Nächstes prüfen Sie schnell, ob Sie auf dieses Paar oder besser gesagt auf den Wertteil in mapExample zugreifen können sowie weakMapExample . Nach dieser Prüfung setzen Sie den objExample bis null damit die Garbage Collection es aus dem Speicher entfernen kann. Abschließend überprüfen Sie noch einmal kurz, ob Sie noch auf den Wertteil zugreifen können.

Wie Sie sehen können, greifen Sie mit get() auf den Wert zu es gibt korrekt undefined zurück für beide die Map (mapExample ) sowie die WeakMap (weakMapExample ). Was aber, wenn Sie versuchen, über Map zu iterieren? (mapExample ) mit for...of Schleife? Sie erhalten immer noch den Wert und sogar den objExample Objekt, selbst nachdem die Garbage Collection ihre Arbeit erledigt hat!

///
// Map and WeakMap example:
// Create new Map and WeakMap.
let mapExample = new Map()
let weakMapExample = new WeakMap()

// Create the objExample.
let objExample = {age: 'foo'}

// Output the content of objExample
console.log(objExample)
// [object Object] {
//   age: 'foo'
// }

// Add the objExample to Map and WeakMap
mapExample.set(objExample, 'foo')
weakMapExample.set(objExample, 'foo')

// Output the content of map and weakMap
for (let [key, value] of mapExample) {
  console.log(key)
  console.log(value)
}
// Outputs:
// [object Object] {
//   age: 'foo'
// }
// 'foo'

// Output the content of Map
console.log(mapExample.get(objExample))
// Outputs: 'foo'

// Output the content of WeakMap
console.log(weakMapExample.get(objExample))
// Outputs: 'foo'

// Set the objExample to null so garbage collection can remove it from memory.
objExample = null

// Output the content of objExample
console.log(objExample)
// Outputs: null

// !
// PAY ATTENTION HERE!
// The map still contains the, now removed, objExample!
// Output the content of Map
for (let [key, value] of mapExample) {
  console.log(key)
  console.log(value)
}
// Outputs:
// [object Object] {
//   age: 'foo'
// }
// 'foo'

// Output the content of Map
console.log(mapExample.get(objExample))
// Outputs: undefined

// Output the content of WeakMap
console.log(weakMapExample.get(objExample))
// Outputs: undefined

WeakSet

Nehmen wir nun das Beispiel mit Map und WeakMap und schreiben Sie es mit Set neu und WeakSet . Was ist, wenn Sie versuchen zu überprüfen, ob das Objekt in Set existiert (setExample ) und WeakSet (weakSetExample ), mit has() ? Vor dem Entfernen erhalten Sie true . Beide, die Set (setExample ) und WeakSet (weakSetExample ) enthalten das Objekt. Wenn Sie versuchen, über Set zu iterieren (setExample ) mit forEach , erhalten Sie das Objekt und seinen Inhalt.

Was passiert nach der Entfernung? Nun, Sie erhalten wieder korrekt false für Set (setExample ) sowie der WeakSet (weakSetExample ). Versuchen Sie es jedoch mit forEach Schleife erneut erhalten Sie wieder das Objekt und seinen Inhalt, obwohl das Objekt selbst nicht mehr existiert.

///
// Set and WeakSet example:
// Create new Set and WeakSet
let setExample = new Set()
let weakSetExample = new WeakSet()

let objExample = {name: 'bar'}

// Output the content of objExample
console.log(objExample)
// [object Object] {
//   name: 'bar'
// }

// Add the objExample to Set and WeakSet
setExample.add(objExample)
weakSetExample.add(objExample)

// Output the content of Set and weakSet
setExample.forEach(item => console.log(item))
// Outputs:
// [object Object] {
//   name: 'bar
// }

// Output the content of Set
console.log(setExample.has(objExample))
// Outputs: true

// Output the content of WeakSet
console.log(weakSetExample.has(objExample))
// Outputs: true

// Set the objExample to null so garbage collection can remove it from memory.
objExample = null

// Output the content of objExample
console.log(objExample)
// Outputs: null

// !
// PAY ATTENTION HERE!
// Output the content of Set
setExample.forEach(item => console.log(item))
// Outputs:
// [object Object] {
//   name: 'bar'
// }

// Output the content of Set
console.log(setExample.has(objExample))
// Outputs: false

// Output the content of WeakSet
console.log(weakSetExample.has(objExample))
// Outputs: false

Die Unterschiede zwischen Map &WeakMap und Set &WeakSet

Der Map , WeakMap , Set und WeakSet sind interessante Features von ES6. Abgesehen von den Namen und der Handhabung der Garbage Collection gibt es weitere Unterschiede zwischen diesen Funktionen. Map und WeakMap und Set und WeakSet sind sich in ihren Unterschieden sehr ähnlich. Zuerst WeakMap und WeakSet Schlüssel können keine primitiven Typen sein (String, Zahl, Boolesch, Null, Undefiniert, Symbol). WeakMap und WeakSet kann nur Objekte speichern.

Zweitens WeakMap und WeakSet Schlüssel können auch nicht von einem Array oder einem anderen Satz erstellt werden. Drittens WeakMap und WeakSet Stellen Sie keine Methoden oder Funktionen bereit, die es Ihnen ermöglichen würden, mit dem gesamten Schlüsselsatz zu arbeiten. Das heißt, es gibt kein size oder length Eigenschaft und kein keys() , values() , entries() , forEach() oder for...of .

Aus diesem Grund haben Sie im obigen Beispiel auch forEach gesehen Wird nur mit Set verwendet , nicht mit WeakSet und for...of nur mit Map aber nicht mit WeakMap . Viertens WeakMap und WeakSet sind nicht iterierbar.

Export, Import und Module

Die export und import -Anweisungen sind wahrscheinlich eine der am häufigsten verwendeten ES6-Funktionen unter JavaScript-Entwicklern. Diese Anweisungen ermöglichen es Ihnen, Ihren Code in Module aufzuteilen, die Sie dann exportieren und importieren können, wann immer Sie möchten oder müssen. Dadurch wird es für Sie viel einfacher, Ihren Code frei von redundanten Wiederholungen zu halten.

Die Importanweisung

Bevor Sie diese ES6-Funktionen in die Hände bekommen, müssen Sie etwas wissen. Sie können import nicht verwenden -Anweisung in eingebetteten Skripts standardmäßig. Wenn Sie dies tun möchten, müssen Sie dessen type festlegen Attribut zu „Modul“. Eine weitere interessante Sache auf dem import ist, dass Sie den Namen des importierten Exports oder mehrerer beim Importieren ändern können.

Verwenden Sie dazu as (import foo as bar from 'module' ). Sie können auch alle Exporte oder Codes aus einem Modul mit * importieren . Wenn Sie einige Exporte aus dem Modul importieren möchten, können Sie dies tun, indem Sie diese Exporte durch Kommas trennen und sie mit geschweiften Klammern umschließen (import { exportOne, exportTwo } from 'module' ).

Wenn Sie etwas exportieren, achten Sie darauf und denken Sie daran, wie Sie es exportieren. Denken Sie also daran, ob Sie das Ding als default exportiert haben exportieren oder nicht (oder als „benannt“). Dies bestimmt die import Syntax, die Sie verwenden müssen, um diesen Export zu importieren. Wenn Sie etwas als default exportieren export verwendest du keine geschweiften Klammern (import defaulExport from 'module' ).

Wenn Sie etwas als „benannten“ Export exportieren, müssen Sie geschweifte Klammern verwenden (import { namedExport } from 'module' ). Zwei letzte Dinge zur Verwendung von import Aussage, die Sie kennen und sich merken müssen. Schließen Sie zunächst den Namen des Exports, Standard oder Named, nicht in Anführungszeichen ein. Zweitens:Schließen Sie den Namen des Moduls, der Datei, aus der Sie den Export importieren, immer in Anführungszeichen ein.

///
// Import example no.1: Basic syntax and importing named export
import { someNamedExport } from '/exampleModule.js'


///
// Import example no.2: Importing multiple named exports
import { foo, bar, bazz, gazz } from '/exampleModule.js'


///
// Import example no.3: Basic syntax and importing default export
import someDefaultExport from '/exampleModule.js'


///
// Import example no.4: Importing default and named export
import someDefaultExport, { someNamedExport } from '/exampleModule.js'


///
// Import example no.5: Importing named export and renaming it
import { someBadlyNamedNamedExportThatIsJustImpossibleToRemember as calc }
  from '/exampleModule.js'


///
// Import example no.6: Importing default export and renaming it
import someBadlyNamedDefaultExportThatIsJustImpossibleToRemember as fuzzy
  from '/exampleModule.js'


///
// Import example no.7: Importing multiple exports and renaming them
import { foo as bar, bazz as fuzzy, zazz as zizzy } from '/exampleModule.js'

Die Exportanweisung

Sie wissen, was Sie über import brauchen Aussagen. Lassen Sie uns nun kurz über export sprechen . Wie ich oben erwähnt habe, gibt es zwei Arten von Exporten, „Standard“ und „benannt“. Wie Sie jetzt wissen, bestimmt die Art des Exports, welche Syntax Sie für den Import verwenden. Import mit geschweiften Klammern mit „benanntem“ Export und ohne geschweiften Klammern mit „Standard“-Export.

Die Regeln zu geschweiften Klammern haben Sie im Teil über „named“ und „default“ gelernt import Aussagen gelten auch für den Export. Wenn Sie etwas als „Standard“ exportieren möchten, verwenden Sie keine geschweiften Klammern. Wenn Sie es als „benannten“ Export exportieren möchten, verwenden Sie geschweifte Klammern.

Ein weiterer wichtiger Unterschied zwischen „default“ und „named“ ist, dass Sie nur einen „default“-Export pro Modul (Datei) haben können. Sie können den „Standard“-Export nicht verwenden, um mehrere Dinge zu exportieren. Diese Beschränkung gilt nicht für „benannte“ Exporte. Sie können so viele „benannte“ Exporte pro Modul (Datei) haben, wie Sie möchten. Mehrere Exporte müssen durch Kommas getrennt werden.

Wenn Sie als Nächstes mehrere Dinge exportieren möchten, können Sie dies entweder einzeln oder alle auf einmal tun. Eine letzte Sache. Was können Sie exportieren? Im Grunde alles. Sie können Variablen, Funktionen, Klassen, Objekte exportieren. Die einzige Einschränkung sind wahrscheinlich Primitive. Das heißt, Sie können Dinge wie Zeichenfolgen, Zahlen, boolesche Werte usw. nicht direkt importieren.

Wenn Sie einen primitiven Datentyp exportieren möchten, müssen Sie ihn zuerst als Variable deklarieren. Anschließend können Sie diese Variable exportieren. Schließlich können Sie das Objekt, das Sie exportieren möchten, auch umbenennen, wenn Sie es exportieren. Dies funktioniert ähnlich wie beim Importieren. Sie verwenden wieder as (export foo as bar ).

///
// Export example no.1: Default export
const foo = 'Export me'

export default foo

// or
export default const foo = 'Export me'


///
// Export example no.2: Named export
const foo = 'Export me'

export { foo }

// or
export const foo = 'Export me'


///
// Export example no.3: Multiple individual exports
export const foo = 13
export const fizz = 'Another export'
export const bazzy = true


///
// Export example no.4: Multiple exports at once
const foo = 13
const fizz = 'Another export'
const bazzy = true

export { foo, fizz, bazzy }


///
// Export example no.5: Named and default exports
const foo = 'Default export'
const fizz = 'named export'
export foo, { fizz }

// or
export default const foo = 'Default export'

export const fizz = 'named export'

Dynamische Importe

Die import und export Anweisungen, die in ES6 eingeführt wurden, sind großartige Funktionen. Ein kleines Upgrade ist jedoch bereits in Vorbereitung. Dies existiert derzeit nur als Stufe 3-Vorschlag. Möglicherweise können Sie Module nur dann dynamisch importieren, wenn Sie sie benötigen. Sie importieren das Modul grundsätzlich bei Bedarf und nicht standardmäßig. Dies wird mit „dynamischem Import“ oder import() erlaubt .

Beispielsweise können Sie ein Modul nur dann importieren, wenn der Benutzer auf eine bestimmte Schaltfläche oder einen bestimmten Link klickt. Oder Sie können die ganze Seite nur dann importieren, wenn der Benutzer auf einen bestimmten Navigationslink klickt. Andernfalls wird das Modul nicht vom Browser oder der App geladen. Dies kann Ihnen dabei helfen, die Menge an Ressourcen, die die Seite laden muss oder muss, erheblich zu reduzieren. Und als Ergebnis kann es viel schneller geladen werden.

Das Beste am dynamischen Import ist, dass Sie ihn überall verwenden können. Sie können es im globalen Bereich, innerhalb von Funktionen oder sogar innerhalb von Anweisungen wie if else verwenden oder Schleifen. Wie es funktioniert? Der dynamische Import gibt immer einen promise zurück . Und dieses Versprechen wird immer in das Modul aufgelöst, das Sie importieren möchten.

Außerdem, wenn Sie mit asynchronem Code oder async arbeiten Funktionen können Sie auch dynamische Importe mit await kombinieren Operator. Sie erfahren etwas über promise und async/await im nächsten Teil dieser Serie.

///
// Dynamic import example no.1:
const button = document.querySelector('.cta-btn')
const navLinkAbout = document.querySelector('.link-about')

// Attach eventListener to the button
button.addEventListener(() => {
  // import specific module when it is needed
  import('/some-module.js').then((module) => {
    // do something
  }).catch((error) => console.log(error))
})

// Attach eventListener to the navigation link
navLinkAbout.addEventListener(() => {
  // import About page module when user clicks on the navigation link
  import('/pages/page-about.js').then((module) => {
    // Load the page
  }).catch((error) => console.log(error))
})


///
// Dynamic import example no.2: Dynamic import and async/await
async function someCoolModuleLoader() {
  // Load module combining import with await
  let coolModule = await import('/cool-module.js')

  coolModule.greet() // Use greet() function from coolModule
  coolModule.default() // Use the default export
}

Epilog:ES6, ES7, ES8 &Schreiben von modernem JavaScript Teil 5

Herzliche Glückwünsche! Sie haben gerade einen weiteren Teil der ES6-, ES7-, ES8- und Writing Modern JavaScript-Serie abgeschlossen! Heute haben Sie alles Wissenswerte über die Funktionen WeakMap gelernt , WeakSet und export und import Aussagen. Schließlich haben Sie auch etwas über dynamische Importe gelernt. Jetzt können Sie all diese aufregenden Funktionen mit absoluter Zuversicht nutzen.

Im nächsten Teil erfahren Sie mehr über die wahrscheinlich leistungsstärksten und fortschrittlichsten ES6-Funktionen, die Sie finden können. Dazu gehören Funktionen wie Pfeilfunktionen, classes , promises , async/await und generators . Machen Sie sich also bereit, Ihre JavaScript-Kenntnisse auf die höchste Stufe zu bringen.