Avastage JavaScripti sümbolid – võimas funktsioon unikaalsete ja privaatsete objektiomaduste loomiseks, mis parandab koodi hooldatavust ja väldib nimekonflikte.
JavaScripti sümbolid: unikaalsete omaduste võtmete haldamise meisterlikkus
JavaScript, keel, mis on tuntud oma paindlikkuse ja dünaamilise olemuse poolest, pakub mitmesuguseid funktsioone objekti omaduste haldamiseks. Nende hulgas paistavad sümbolid silma kui võimas tööriist unikaalsete ja sageli privaatsete omaduste võtmete loomiseks. See artikkel pakub põhjalikku juhendit sümbolite mõistmiseks ja tõhusaks kasutamiseks teie JavaScripti projektides, käsitledes nende aluseid, praktilisi rakendusi ja täiustatud kasutusjuhte.
Mis on JavaScripti sĂĽmbolid?
ECMAScript 2015 (ES6) versioonis tutvustatud sümbolid on primitiivne andmetüüp, sarnaselt numbritele, sõnedele ja tõeväärtustele. Erinevalt teistest primitiividest on iga sümboli eksemplar aga unikaalne ja muutumatu. See unikaalsus muudab need ideaalseks objekti omaduste loomiseks, mis garanteeritult ei lähe vastuollu olemasolevate või tulevaste omadustega. Mõelge neist kui sisemistest ID-dest oma JavaScripti koodis.
SĂĽmbol luuakse funktsiooni Symbol()
abil. Valikuliselt võite silumise eesmärgil anda kirjelduseks sõne, kuid see kirjeldus ei mõjuta sümboli unikaalsust.
Sümboli põhiline loomine
Siin on lihtne näide sümboli loomisest:
const mySymbol = Symbol("description");
console.log(mySymbol); // Väljund: Symbol(description)
Oluline on märkida, et isegi kui kaks sümbolit luuakse sama kirjeldusega, on need siiski erinevad:
const symbol1 = Symbol("same description");
const symbol2 = Symbol("same description");
console.log(symbol1 === symbol2); // Väljund: false
Miks kasutada sĂĽmboleid?
Sümbolid lahendavad mitmeid levinud väljakutseid JavaScripti arenduses:
- Nimekonfliktide vältimine: Suurte projektide või kolmandate osapoolte teekidega töötades võivad nimekonfliktid olla märkimisväärne probleem. Sümbolite kasutamine omaduste võtmetena tagab, et teie omadused ei kirjuta kogemata olemasolevaid omadusi üle. Kujutage ette stsenaariumi, kus te laiendate Tokyos asuva arendaja loodud teeki ja soovite lisada uue omaduse selle teegi hallatavale objektile. Sümboli kasutamine hoiab ära olukorra, kus te kogemata kirjutate üle omaduse, mille nemad on juba defineerinud.
- Privaatsete omaduste loomine: JavaScriptis ei ole tõeliselt privaatseid liikmeid samamoodi nagu mõnes teises keeles. Kuigi on olemas konventsioonid, nagu allkriipsu eesliite kasutamine (
_myProperty
), ei takista need juurdepääsu. Sümbolid pakuvad tugevamat kapselduse vormi. Kuigi need ei ole täielikult läbimatud, muudavad need omadustele väljastpoolt objekti juurdepääsu oluliselt raskemaks, soodustades paremat koodi organiseerimist ja hooldatavust. - Metaprogrammeerimine: Sümboleid kasutatakse metaprogrammeerimises, et defineerida sisseehitatud JavaScripti operatsioonidele kohandatud käitumist. See võimaldab teil kohandada, kuidas objektid suhtlevad keele funktsioonidega nagu iteratsioon või tüübikonversioon.
Sümbolite kasutamine objekti omaduste võtmetena
Sümboli kasutamiseks omaduse võtmena asetage see nurksulgudesse:
const mySymbol = Symbol("myProperty");
const myObject = {
[mySymbol]: "Hello, Symbol!"
};
console.log(myObject[mySymbol]); // Väljund: Hello, Symbol!
Otse omadusele ligipääs punktnotatsiooni abil (myObject.mySymbol
) ei tööta. Peate kasutama sulgudes notatsiooni koos sümboli endaga.
Näide: nimekonfliktide vältimine
Vaatleme olukorda, kus te laiendate kolmanda osapoole teeki, mis kasutab omadust nimega `status`:
// Kolmanda osapoole teek
const libraryObject = {
status: "ready",
processData: function() {
console.log("Processing...");
}
};
// Teie kood (teegi laiendamine)
libraryObject.status = "pending"; // Potentsiaalne konflikt!
console.log(libraryObject.status); // Väljund: pending (üle kirjutatud!)
Sümbolit kasutades saate seda konflikti vältida:
const libraryObject = {
status: "ready",
processData: function() {
console.log("Processing...");
}
};
const myStatusSymbol = Symbol("myStatus");
libraryObject[myStatusSymbol] = "pending";
console.log(libraryObject.status); // Väljund: ready (algne väärtus)
console.log(libraryObject[myStatusSymbol]); // Väljund: pending (teie väärtus)
Näide: poolprivaatsete omaduste loomine
Sümboleid saab kasutada omaduste loomiseks, mis on väljastpoolt objekti vähem ligipääsetavad. Kuigi need ei ole rangelt privaatsed, pakuvad need teatud tasemel kapseldust.
class MyClass {
#privateField = 'See on tõeliselt privaatne väli (ES2022)'; // Uus privaatse klassi funktsioon
constructor(initialValue) {
this.publicProperty = initialValue;
this.privateSymbol = Symbol("privateValue");
this[this.privateSymbol] = "Secret!";
}
getPrivateValue() {
return this[this.privateSymbol];
}
}
const myInstance = new MyClass("Initial Value");
console.log(myInstance.publicProperty); // Väljund: Initial Value
//console.log(myInstance.privateSymbol); // Väljund: undefined (Sümbolile ei saa otse ligi)
//console.log(myInstance[myInstance.privateSymbol]); //Töötab klassi sees
//console.log(myInstance.#privateField); //Väljund: Viga väljaspool klassi
console.log(myInstance.getPrivateValue());//secret
Kuigi sümboli omadusele on endiselt võimalik juurde pääseda, kui teate sümbolit, muudab see juhusliku või tahtmatu juurdepääsu palju ebatõenäolisemaks. Uus JavaScripti funktsioon "#" loob tõeliselt privaatseid omadusi.
Tuntud sĂĽmbolid
JavaScript defineerib hulga tuntud sümboleid (nimetatakse ka süsteemi sümboliteks). Nendel sümbolitel on eelnevalt määratletud tähendused ja neid kasutatakse JavaScripti sisseehitatud operatsioonide käitumise kohandamiseks. Neile pääseb ligi kui Symbol
objekti staatilistele omadustele (nt Symbol.iterator
).
Siin on mõned kõige sagedamini kasutatavad tuntud sümbolid:
Symbol.iterator
: Määrab objekti vaikimisi iteraatori. Kui objektil onSymbol.iterator
meetod, muutub see itereeritavaks, mis tähendab, et seda saab kasutadafor...of
tsĂĽklite ja spread-operaatoriga (...
).Symbol.toStringTag
: Määrab objekti kohandatud sõnekirjelduse. Seda kasutatakse, kui objektil kutsutakse väljaObject.prototype.toString()
.Symbol.hasInstance
: Määrab, kas objekti peetakse konstruktorfunktsiooni eksemplariks.Symbol.toPrimitive
: Määrab meetodi objekti teisendamiseks primitiivseks väärtuseks (nt numbriks või sõneks).
Näide: iteratsiooni kohandamine Symbol.iterator
abil
Loome itereeritava objekti, mis itereerib üle sõne märkide vastupidises järjekorras:
const reverseString = {
text: "JavaScript",
[Symbol.iterator]: function* () {
for (let i = this.text.length - 1; i >= 0; i--) {
yield this.text[i];
}
}
};
for (const char of reverseString) {
console.log(char); // Väljund: t, p, i, r, c, S, a, v, a, J
}
console.log([...reverseString]); //Väljund: ["t", "p", "i", "r", "c", "S", "a", "v", "a", "J"]
Selles näites defineerime generaatorfunktsiooni, mis on määratud Symbol.iterator
-ile. See funktsioon tagastab (yield) iga sõne märgi vastupidises järjekorras, muutes reverseString
objekti itereeritavaks.
Näide: tüübikonversiooni kohandamine Symbol.toPrimitive
abil
Saate kontrollida, kuidas objekti teisendatakse primitiivseks väärtuseks (nt matemaatilistes operatsioonides või sõnede liitmisel), defineerides Symbol.toPrimitive
meetodi.
const myObject = {
value: 42,
[Symbol.toPrimitive](hint) {
if (hint === "number") {
return this.value;
}
if (hint === "string") {
return `The value is ${this.value}`;
}
return this.value;
}
};
console.log(Number(myObject)); // Väljund: 42
console.log(String(myObject)); // Väljund: The value is 42
console.log(myObject + 10); // Väljund: 52 (numbriks teisendamine)
console.log("Value: " + myObject); // Väljund: Value: The value is 42 (sõneks teisendamine)
hint
argument näitab, millist tüüpi teisendust üritatakse ("number"
, "string"
või "default"
). See võimaldab teil kohandada teisenduskäitumist vastavalt kontekstile.
SĂĽmbolite register
Kuigi sümbolid on üldiselt unikaalsed, on olukordi, kus te võiksite soovida sümbolit jagada oma rakenduse erinevate osade vahel. Sümbolite register pakub selleks mehhanismi.
Meetod Symbol.for(key)
loob või hangib sümboli globaalsest sümbolite registrist. Kui antud võtmega sümbol on juba olemas, tagastab see selle sümboli; vastasel juhul loob see uue sümboli ja registreerib selle võtmega.
const globalSymbol1 = Symbol.for("myGlobalSymbol");
const globalSymbol2 = Symbol.for("myGlobalSymbol");
console.log(globalSymbol1 === globalSymbol2); // Väljund: true (sama sümbol)
console.log(Symbol.keyFor(globalSymbol1)); // Väljund: myGlobalSymbol (hangi võti)
Meetod Symbol.keyFor(symbol)
hangib võtme, mis on seotud sümboliga globaalses registris. See tagastab undefined
, kui sĂĽmbolit ei loodud Symbol.for()
abil.
SĂĽmbolid ja objekti loendamine
Sümbolite üks peamisi omadusi on see, et need ei ole vaikimisi loendatavad. See tähendab, et meetodid nagu Object.keys()
, Object.getOwnPropertyNames()
ja for...in
tsüklid ignoreerivad neid. See suurendab veelgi nende kasulikkust "peidetud" või sisemiste omaduste loomisel.
const mySymbol = Symbol("myProperty");
const myObject = {
name: "John Doe",
[mySymbol]: "Hidden Value"
};
console.log(Object.keys(myObject)); // Väljund: ["name"]
console.log(Object.getOwnPropertyNames(myObject)); // Väljund: ["name"]
for (const key in myObject) {
console.log(key); // Väljund: name
}
SĂĽmbolite omaduste hankimiseks peate kasutama Object.getOwnPropertySymbols()
:
const mySymbol = Symbol("myProperty");
const myObject = {
name: "John Doe",
[mySymbol]: "Hidden Value"
};
console.log(Object.getOwnPropertySymbols(myObject)); // Väljund: [Symbol(myProperty)]
Veebilehitsejate ĂĽhilduvus ja transpileerimine
Sümbolid on toetatud kõikides kaasaegsetes veebilehitsejates ja Node.js versioonides. Kui teil on aga vaja toetada vanemaid veebilehitsejaid, peate võib-olla kasutama transpilaatorit nagu Babel, et teisendada oma kood ühilduvaks JavaScripti versiooniks.
Parimad praktikad sĂĽmbolite kasutamisel
- Kasutage sümboleid nimekonfliktide vältimiseks, eriti kui töötate väliste teekide või suurte koodibaasidega. See on eriti oluline koostööprojektides, kus mitu arendajat võivad töötada sama koodiga.
- Kasutage sümboleid poolprivaatsete omaduste loomiseks ja koodi kapselduse parandamiseks. Kuigi need ei ole tõeliselt privaatsed liikmed, pakuvad nad olulist kaitset juhusliku juurdepääsu eest. Kaaluge privaatsete klassi funktsioonide kasutamist rangema privaatsuse tagamiseks, kui teie sihtkeskkond seda toetab.
- Kasutage tuntud sümboleid sisseehitatud JavaScripti operatsioonide ja metaprogrammeerimise käitumise kohandamiseks. See võimaldab teil luua väljendusrikkamat ja paindlikumat koodi.
- Kasutage sĂĽmbolite registrit (
Symbol.for()
) ainult siis, kui peate sĂĽmbolit jagama oma rakenduse erinevate osade vahel. Enamikul juhtudel onSymbol()
abil loodud unikaalsed sümbolid piisavad. - Dokumenteerige oma sümbolite kasutamine koodis selgelt. See aitab teistel arendajatel mõista nende omaduste eesmärki ja kavatsust.
Täiustatud kasutusjuhud
- Raamistike arendus: Sümbolid on raamistike arenduses uskumatult kasulikud sisemiste olekute, elutsükli konksude ja laienduspunktide defineerimiseks, sekkumata kasutaja määratletud omadustesse.
- Pluginate süsteemid: Pluginate arhitektuuris saavad sümbolid pakkuda pluginatele turvalist viisi põhiliste objektide laiendamiseks, riskimata nimekonfliktidega. Iga plugin saab defineerida oma sümbolite komplekti oma spetsiifiliste omaduste ja meetodite jaoks.
- Metaandmete salvestamine: SĂĽmboleid saab kasutada metaandmete lisamiseks objektidele mitte-invasiivsel viisil. See on kasulik teabe salvestamiseks, mis on oluline konkreetses kontekstis, ilma et see koormaks objekti ebavajalike omadustega.
Kokkuvõte
JavaScripti sümbolid pakuvad võimsat ja mitmekülgset mehhanismi objekti omaduste haldamiseks. Mõistes nende unikaalsust, mitte-loendatavust ja seost tuntud sümbolitega, saate kirjutada robustsemat, hooldatavamat ja väljendusrikkamat koodi. Olenemata sellest, kas töötate väikese isikliku projekti või suure ettevõtte rakenduse kallal, aitavad sümbolid teil vältida nimekonflikte, luua poolprivaatseid omadusi ja kohandada sisseehitatud JavaScripti operatsioonide käitumist. Võtke sümbolid omaks, et täiustada oma JavaScripti oskusi ja kirjutada paremat koodi.