DıÅa aktarma ve dahil etme yönergeleri çok yönlüdür.
Ãnceki bölümde basit bir kullanımı gördük. Åimdi daha fazla örnek keÅfedelim.
Bildirimler Ãnce DıÅa Aktarım
Bir deÄiÅken, fonksiyon ya da bir sınıf olsun, herhangi bir bildirimi önce export diyerek dıÅa aktarılmıŠolarak etiketleyebiliriz.
ÃrneÄin, buradaki tüm dıÅa aktarımlar geçerlidir:
// Bir diziyi dıÅarıya atkarma
export let months = ['Jan', 'Feb', 'Mar','Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
// Bir sabiti dıÅarıya aktarma
export const MODULES_BECAME_STANDARD_YEAR = 2015;
// Bir sınıfı dıÅarıya aktarma
export class User {
constructor(name) {
this.name = name;
}
}
Unutmayın ki, bir sınıf veya fonksiyondan önce export bir iÅlev ifadeleri yapmaz. DıÅarıya aktarılmasına raÄmen hala bir iÅlev bildirgesidir.
JavaScript stil kılavuzlarının çoÄu ifadelerden sonra noktalı virgül önermektedir ama iÅlev ve sınıf bildirimlerinden sonra deÄil.
Bu nedenle export class ve export function sonuna noktalı virgül konulmamalıdırâ¦
export function sayHi(user) {
alert(`Hello, ${user}!`);
} // sonunda ; yok
Bildirimlerden ayrı dıÅa aktarma
Ayrıca, export ayrı ayrı koyabiliriz.
Burada önce bildirir sonra dıÅarıya aktarırız:
// ð say.js
function sayHi(user) {
alert(`Hello, ${user}!`);
}
function sayBye(user) {
alert(`Bye, ${user}!`);
}
export {sayHi, sayBye}; // dıÅa aktarıların deÄiÅkenlerin listesi
â¦Veya teknik olarak export fonksiyonların üstüne koyabiliriz.
İmport *
Genelde, import {...} içine neyin içine aktarılacaÄını içeren bir liste koyarız, Åöyle:
// ð main.js
import {sayHi, sayBye} from './say.js';
sayHi('John'); // Hello, John!
sayBye('John'); // Bye, John!
Ama liste uzunsa, import * as <obj> kullanarak her Åeyi nesne olarak alabiliriz, örneÄin:
// ð main.js
import * as say from './say.js';
say.sayHi('John');
say.sayBye('John');
İlk bakıÅta, âher Åeyi dahil etmekâ kısa yazıldıÄı için güzel gözüküyor. İçeriye aktarmamız için neye ihtiyaç varsa neden açıkça listeleyelim?
Bunun birkaç nedeni var.
-
Modern derleme araçları (webpack ve diÄerleri) modülleri bir araya getirir ve kullanılmasını önleyen yükleme iÅlemlerini hızlandırmak ve kaldırmak için optimize eder.
Diyelim ki, birçok fonksiyona sahip projemize 3. parti bir kütüphane
lib.jsekledik.// ð lib.js export function sayHi() { ... } export function sayBye() { ... } export function becomeSilent() { ... }Åimdi projemizde
lib.jsfonksiyonlarından sadece birini kullanırsak// ð main.js import {sayHi} from './lib.js';â¦Ardından optimizer otomatik olarak algılar ve diÄer iÅlevleri birlikte verilen koddan tamamen kaldırır, böylece yapı daha küçük hale gelir. Buna âtree-shakingâ denilir.
-
Açıkça listelemek ne içeri aktarılacaksa daha kısa isimler verilir:
lib.sayHi()yerinesayHi(). -
Açıkça dahil etmek kod yapısında daha iyi genel bakıÅı saÄlar: Nerede, ne kullanılır. Kod desteÄini ve yeniden düzenlemeyi kolaylaÅtırır.
Import âasâ
Farklı isimler altında içeriye aktarmak için as da kullanabiliriz.
ÃrneÄin, Hadi kısa olması için sayHi deÄiÅkenini hi yerel deÄiÅken içine alalım. Aynı Åekilde sayBye içinde:
// ð main.js
import {sayHi as hi, sayBye as bye} from './say.js';
hi('John'); // Hello, John!
bye('John'); // Bye, John!
Export âasâ
Benzer sözdizimleri export içinde var.
Hadi fonksiyonları hi ve bye olarak dıÅarıya aktaralım:
// ð say.js
...
export {sayHi as hi, sayBye as bye};
Åimdi hi ve bye dıÅarıdakiler için resmi isimler:
// ð main.js
import * as say from './say.js';
say.hi('John'); // Hello, John!
say.bye('John'); // Bye, John!
export default
Åimdiye kadar, Birden çok Åeyi içeriye/dıÅarıya aktaracaÄımızı gördük, isteÄe baÄlı olarak âasâ diÄer isimler.
Pratikte, modüller Åunlardan birini içerir:
- Bir kütüphane, fonksiyonlar paketi,
lib.jsgibi. - Veya bir varlık,
user.jsdeclass UsertanımlanmıÅtır. Bütün modül bu sınıfa sahiptir.
ÃoÄunlukla ikinci yaklaÅım tercih edilir. Böylece her âÅeyâ kendi modülünde bulunur.
DoÄal olarak bu çok fazla dosya gerektirir, her Åeyin kendi modülünü istediÄi gibi, ama bu hiç sorun deÄil. Aslında, dosyalar iyi adlandırılmıÅsa ve klasörler halinde yapılandırılmıÅsa kod gezinme iÅlemi kolaylaÅır.
Modüller, âmodül baÅına bir Åeyinâ daha iyi görünmesini saÄlamak için özel export default sözdizimi saÄlar.
export ve import ifadesini takip etmesi gerekir:
- Modulün "main export"tan önce
export defaultkoyun - Süslü parantez olmadan
importçaÄırın.
ÃrneÄin, burada user.js class User ı dıÅarıya aktarır:
// ð user.js
export default class User { // sadece "default" ekle
constructor(name) {
this.name = name;
}
}
â¦ve main.jsde içeriye aktarılır:
// ð main.js
import User from './user.js'; // {User} deÄir, sadece User
new User('John');
Süslü parantezler olmadan içeri aktarmalar daha güzel görünür. Modülleri kullanmaya baÅlarken görülen yaygın hatalardan biri süslü parantezleri tamamen unutmaktır. Bu nedenle, unutmayın. import adlandırılmıŠiçeriye aktarma iÅlemleri için süslü parantezler gereklidir ama varsayılan için bunlara gerek yoktur.
| AdlandırılmıŠİçeriye Aktarılanlar | Varsayılan İçeriye Aktarılanlar |
|---|---|
export class User {...} |
export default class User {...} |
import {User} from ... |
import User from ... |
DoÄal olarak, dosya baÅına yalnızca bir âvarsayılanâ dıÅa aktarma olabilir.
Tek bir modülde hem varsayılan hem de adlandırılmıŠiçeriye aktarma yapabiliriz ancak pratikte insanlar genellikle bunu karıÅtırmaz. Bir modül, dıÅa aktarma adını verir veya varsayılan olanıdır.
Unutulmaması gereken bir baÅka Åey de, dıÅa aktarma adının (doÄal olarak) bir adı olması gerekirken, export default adsız olabilir.
ÃrneÄin, Bunların hepsi mükemmel ve doÄru default export kullanımları:
export default class { // sınıf adı yok
constructor() { ... }
}
export default function(user) { // fonksiyon adı yok
alert(`Hello, ${user}!`);
}
// bir deÄiÅken yapmadan tek bir deÄer dıÅarıya aktar
export default ['Jan', 'Feb', 'Mar','Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
Bu iyi çünkü export default dosya baÅına yalnızca bir tanesidir. Bunun aksine, adlandırılmıŠiçeriye aktarma için bir adın çıkarılması bir hata olur:
export class { // Hata! (non-default export needs a name)
constructor() {}
}
âDefaultâ Takma Adı
âdefaultâ anahtar sözcüÄü, varsayılan içeriye aktarma, baÄımsız içeriye aktarma ve referans göstermemiz gerektiÄinde diÄer senaryolar için âtakma adâ kullanılır.
ÃrneÄin, önceden bildirilmiÅ bir iÅlevimiz varsa , iÅte bunu export default nasıl yaparız (tanımdan ayrı olarak):
function sayHi(user) {
alert(`Hello, ${user}!`);
}
export {sayHi as default}; // fonksiyondan önce "export default" eklediÄimiz gibi
Ya da bir user.js modulünün bir ana âvarsayılanâ Åeyi ve birkaç tane adlandırılmıŠolanı dıÅarı aktarıldıÄını varsayalım.
// ð user.js
export default class User {
constructor(name) {
this.name = name;
}
}
export function sayHi(user) {
alert(`Hello, ${user}!`);
}
Varsayılan dıÅa aktarma adını adlandırılmıŠolanla birlikte Åu Åekilde alabiliriz:
// ð main.js
import {default as User, sayHi} from './user.js';
new User('John');
Ya da * nesnesini almayı düÅünürsek default özelliÄi tam olarak varsayılan içeriye aktarmadır:
// ð main.js
import * as user from './user.js';
let User = user.default;
new User('John');
Varsayılan içeriye aktarmayı kullanmalı mıyım?
Varsayılan dıÅa aktarım kullanımlarında dikkat edilmelidir. Ãünkü bakımı daha zordur.
AdlandırılmıŠaçıktır. Aldıkları Åeyi tam olarak açıklıyorlar. Bu yüzden onlardan bu bilgilere sahibiz. Bu iyi bir Åey.
Ayrıca, adlandırılmıŠdıÅa aktarma iÅlemleri bizi içe aktarmak için doÄru adı kullanmaya zorlar:
import {User} from './user.js';
// import {MyUser} çalıÅmayacak, adı {User} olmalı
Varsayılan içeriye aktarma için içeriye aktarırken her zaman adı seçeriz:
import User from './user.js'; // çalıÅır
import MyUser from './user.js'; // çalıÅır
// Bir Åey içeriye aktarılabilir..., ve çalıÅacaktır
Yani, kötüye kullanılabilecek biraz daha fazla özgürlük var. Böylece ekip üyeleri aynı Åey için farklı isimler kullanabilirler.
Genelde, bundan kaçınmak ve kodu tutarlı tutmak için içe aktarılan deÄiÅkenlerin dosya adlarına karÅılık gelmesi gerektiÄi bir kural vardır:
import User from './user.js';
import LoginForm from './loginForm.js';
import func from '/path/to/func.js';
...
BaÅka bir çözüm, her yerde adlandırılmıŠiçeriye aktarım kullanmak olacaktır. Sadece tek bir Åey içeriye aktarılsa bile yine de default olmadan bir isim altında içeriye aktarılır.
Bu da re-export (aÅaÄıda göreceksin) biraz daha kolay hale gelir.
Yeniden dıÅa aktarma
âYeniden dıÅa aktarmaâ söz dizimi export ... from ... Åeyleri içeriye aktarmasına ve hemen (baÅka bir isim altında) içeriye aktarmasına izin verir:
export {sayHi} from './say.js';
export {default as User} from './user.js';
Amaç ne? Neden bu gerekli? Pratik bir kullanım örneÄi görelim.
Bir âpaketâ yazdıÄımızı düÅünelim: dıÅarıda dıÅa aktarılan fonksiyonelliklerin bir kısmı ile çoÄunlukla dahili olarak ihtiyaç duyulan birçok modüle sahip bir klasör (NPM gibi araçlar paketleri yayınlamaya ve daÄıtmaya izin verir, ancak burada önemi yoktur).
Bir klasör yapısı Åöyle olabilir:
auth/
index.js
user.js
helpers.js
tests/
login.js
providers/
github.js
facebook.js
...
Paket iÅlevselliÄini tek bir giriÅ noktası üzerinden göstermek istiyoruz, âana dosyaâ auth/index.js böyle kullanılmalı:
import {login, logout} from 'auth/index.js'
Buradaki fikir, paketimizi kullanan geliÅtiricilerin iç yapısıyla karıÅmaması gerektiÄidir. Paket klasörümüzdeki dosyaları aramamalılar. Sadece auth/index.jsde gerekli olanları dıÅarıya aktarıyoruz ve gerisini meraklı gözlerden gizleriz.
Åimdi, dıÅa aktarılan gerçek iÅlevsellik paketin arasına daÄılmıŠolduÄundan, paket içinde âYeniden dıÅa aktarmaâ ve toplayabiliriz:
auth/index.js:
// ð auth/index.js
import {login, logout} from './helpers.js';
export {login, logout};
import User from './user.js';
export {User};
import Github from './providers/github.js';
export {Github};
...
âYeniden dıÅa aktarmaâ bunun için sadece kısa bir gösterimidir:
// ð auth/index.js
export {login, logout} from './helpers.js';
// ya da tüm yardımcıları yeniden dıÅa aktarma için kullanabiliriz.
// export * from './helpers.js';
export {default as User} from './user.js';
export {default as Github} from './providers/github.js';
...
Lütfen unutmayın: export User from './user.js' çalıÅmayacak. Bu aslında sözdizimi hatası. Varsayılan içeriye aktarmayı yeniden dıÅa aktarım için açıkça belirtmeliyiz {default as ...}. Yukarıdaki örnekte olduÄu gibi.
Ayrıca, baÅka bir tuhaflık var: export * from './user.js' varsayılan olan haric, yalnızca adlandırılmıŠdıÅa aktarımlar yeniden dıÅa aktarılır. Bir kez daha açıkça söylemeliyiz.
ÃrneÄin, her Åeyi yeniden dıÅa aktarmak için iki ifade gerekli olacaktır:
export * from './module.js'; // adlandırılmıŠdıÅarıya aktarımı yeniden dıÅarıya aktarmak için
export {default} from './module.js'; // varsayılanı yeniden dıÅarıya aktarmak için
Varsayılan deÄer açıkça yalnızca yeniden dıÅa aktarırken belirtilmelidir import * as obj iyi çalıÅır. Varsayılan dıÅa aktarımı obj.default olarak alır. Yani burada içe aktarım ve dıÅa aktarım yapıları arasında hafif bir asimetri var.
Ãzetle
AÅaÄıda export türleri vardır:
- Bildirmeden önce:
export [default] class/function/variable ...
- BaÄımsız:
export {x [as y], ...}.
- Yeniden dıÅa aktarma:
export {x [as y], ...} from "mod"export * from "mod"(varsayılan yeniden dıÅa aktarmaz).export {default [as y]} from "mod"(varsayılanı yeniden dıÅa aktar).
İçeriye Aktarma:
- Modülden adlandırılmıŠiçeri aktarma:
import {x [as y], ...} from "mod"
- Varsayılan içeri aktarma:
import x from "mod"import {default as x} from "mod"
- Her Åey:
import * as obj from "mod"
- Modulü içeriye aktarın (çalıÅır) ama deÄiÅkene atamayın:
import "mod"
Import/export ifadelerini bir komut dosyasının en üstüne veya en altına koyabiliriz. Fark etmez.
Yani teknik olarak bu iyi:
sayHi();
// ...
import {sayHi} from './say.js'; // script'in sonunda içe aktar
Uygulamada, daha iyi rahatlık için içeriye aktarma genellikle dosyanın baÅındadır.
Unutmayın ki, import/export ifadeleri {...} içindeyse çalıÅmaz.
Bunun gibi koÅullu bir içe aktarma çalıÅmaz:
if (something) {
import {sayHi} from "./say.js"; // Hata: içe aktarma en üst düzeyde olmalı
}
â¦Ama ya bir Åeyi gerçekten Åartlı olarak içeri aktarmamız gerekiyorsa? Ya da doÄru zamanda? ÃrneÄin, gerçekten ihtiyaç duyulduÄunda istek üzerine bir modül yükleme?
Bir sonraki bölümde dinamik içeriye aktarma göreceÄiz.
Yorumlar
<code>kullanınız, birkaç satır eklemek için ise<pre>kullanın. EÄer 10 satırdan fazla kod ekleyecekseniz plnkr kullanabilirsiniz)