Posty

Javascript named export vs. default export - zrozum różnicę raz a dobrze!

Named vs default export

💡 TL; DR;
Od razu chcesz poznać wyjaśnienie, a nie interesują Cie wyniki kompilacji? 👉👉👉 Wyjaśnienie.

Mamy dwa rodzaje exportów,

export foo; // named export
export default foo; // default export

które po kompilacji, wyglądają tak:

exports.foo = foo;
exports['default'] = foo;

Następnie mamy dwa rodzaje importów,

import {foo} from 'blah';
import foo from 'blah';

które po kompilacji, wyglądają tak:

var foo = require('blah').foo;
var foo = require('blah')['default'];

Dlaczego to działa tak, a nie inaczej ? Tutaj w końcu to zrozumiesz 🙂

Załóżmy, że mamy pustą klasę Human tak jak w kodzie poniżej. Klasa celowo jest pusta, skupiamy się na zrozumieniu importów i exportów, a implementacja klasy nie jest istotna (zamiast klasy moglibyśmy eksportować funkcję, obiekt czy cokolwiek innego-nie ważne).

// human.ts

export class Human{}

Zwróć proszę uwagę na formę export’u - to named export.

Na podstawie klasy human, którą eksportujemy poprzez “named export”, wyobraź sobie, że pod spodem tak naprawdę eksportowany jest obiekt z kluczem o nazwie Human. W kodzie wyglądałoby to tak:

// human.ts

export { Human: class {} }

Dlatego właśnie import tak zwanych, “named exports” wygląda tak:

import { Human } from './human.ts';

Tak naprawdę importujesz klucze obiektu o określonych z góry nazwach.

💡 Pamiętaj, że skoro importujesz obiekt o z góry określonych nazwach kluczy, to przy imporcie nazwy kluczy muszą się pokrywać. Możesz je natomiast zmapować na dowolną inną nazwę używając operatora `as`. Na przykład tak:
import { Human as SuperHuman } from './human.ts';

Właśnie zrozumiałeś named exports, to teraz zrozum default exports 👇

W przypadku kiedy mamy do czynienia z default export np.

export default class Human{}

// lub

class Human{};

// i 500 linijek później...
export default Human;

To pod spodem też exportowany jest obiekt, ale z kluczem default. Wygląda to mniej więcej tak:

export { default: Human };

Importować taki obiekt możemy w różny sposób, a najczęściej robimy to tak:

import Human from './human.ts'

// lub np.

import { default as Human } from './human.ts'

Zagadką jest, że skoro pod spodem exportowany jest obiekt o kluczu default, to skąd przy exporcie pisanym w ten sposób:

import Human from './human.ts'

Kompilator wie, że chodzi nam o to co kryje się pod kluczem default?

W trakcie takiego importu kompilator “w locie” wyciąga wartość, która jest zapisana pod kluczem default. Wygląda to mniej więcej tak:

export {default: Human}['default'];

Dzięki zapisowi [’default’] tuż za eksportowanym obiektem, kompilator odnosi się od razu do klasy Human, która była przypisana pod kluczem default i zwraca bezpośrednio te klasę 🙂

Pozdrawiam i do zobaczenia w następnym poście!