Eesti

Avastage JavaScripti sümbolid: nende eesmärk, loomine, kasutamine unikaalsete võtmete ja metaandmete jaoks ning nimekonfliktide vältimine. Praktilised näited.

JavaScripti sümbolid: unikaalsed omaduste võtmed ja metaandmed

JavaScripti sümbolid, mis võeti kasutusele ECMAScript 2015-s (ES6), pakuvad mehhanismi unikaalsete ja muutumatute omaduste võtmete loomiseks. Erinevalt stringidest või numbritest on sümbolid garanteeritult unikaalsed kogu teie JavaScripti rakenduses. Need pakuvad viisi nimekonfliktide vältimiseks, metaandmete lisamiseks objektidele olemasolevaid omadusi segamata ja objektide käitumise kohandamiseks. See artikkel annab põhjaliku ülevaate JavaScripti sümbolitest, hõlmates nende loomist, rakendusi ja parimaid tavasid.

Mis on JavaScripti sümbolid?

Sümbol on primitiivne andmetüüp JavaScriptis, sarnaselt numbrite, stringide, tõeväärtuste, nulli ja undefined-iga. Kuid erinevalt teistest primitiivsetest tüüpidest on sümbolid unikaalsed. Iga kord, kui loote sümboli, saate täiesti uue, unikaalse väärtuse. See unikaalsus muudab sümbolid ideaalseks:

Sümbolite loomine

Sümboli loomiseks kasutatakse konstruktorit Symbol(). On oluline märkida, et te ei saa kasutada new Symbol(); sümbolid ei ole objektid, vaid primitiivsed väärtused.

Sümboli põhiline loomine

Lihtsaim viis sümboli loomiseks on:

const mySymbol = Symbol();
console.log(typeof mySymbol); // Väljund: symbol

Iga Symbol() väljakutse genereerib uue, unikaalse väärtuse:

const symbol1 = Symbol();
const symbol2 = Symbol();
console.log(symbol1 === symbol2); // Väljund: false

Sümbolite kirjeldused

Sümboli loomisel saate anda valikulise string-kirjelduse. See kirjeldus on kasulik silumiseks ja logimiseks, kuid see ei mõjuta sümboli unikaalsust.

const mySymbol = Symbol("myDescription");
console.log(mySymbol.toString()); // Väljund: Symbol(myDescription)

Kirjeldus on puhtalt informatiivne; kaks sama kirjeldusega sümbolit on siiski unikaalsed:

const symbolA = Symbol("same description");
const symbolB = Symbol("same description");
console.log(symbolA === symbolB); // Väljund: false

Sümbolite kasutamine omaduste võtmetena

Sümbolid on eriti kasulikud omaduste võtmetena, kuna need tagavad unikaalsuse, vältides nimekonflikte objektidele omaduste lisamisel.

Sümbol-omaduste lisamine

Sümboleid saab kasutada omaduste võtmetena täpselt nagu stringe või numbreid:

const mySymbol = Symbol("myKey");
const myObject = {};

myObject[mySymbol] = "Hello, Symbol!";

console.log(myObject[mySymbol]); // Väljund: Hello, Symbol!

Nimekonfliktide vältimine

Kujutage ette, et töötate kolmanda osapoole teegiga, mis lisab objektidele omadusi. Võiksite lisada oma omadusi, riskimata olemasolevate ülekirjutamisega. Sümbolid pakuvad selleks turvalise viisi:

// Kolmanda osapoole teek (simuleeritud)
const libraryObject = {
  name: "Library Object",
  version: "1.0"
};

// Teie kood
const mySecretKey = Symbol("mySecret");
libraryObject[mySecretKey] = "Top Secret Information";

console.log(libraryObject.name); // Väljund: Library Object
console.log(libraryObject[mySecretKey]); // Väljund: Top Secret Information

Selles näites tagab mySecretKey, et teie omadus ei satu konflikti ühegi olemasoleva omadusega objektis libraryObject.

Sümbol-omaduste loendamine

Üks sümbol-omaduste oluline omadus on see, et need on peidetud standardsete loendusmeetodite, nagu for...in tsüklid ja Object.keys(), eest. See aitab kaitsta objektide terviklikkust ja vältida sümbol-omaduste juhuslikku kasutamist või muutmist.

const mySymbol = Symbol("myKey");
const myObject = {
  name: "My Object",
  [mySymbol]: "Symbol Value"
};

console.log(Object.keys(myObject)); // Väljund: ["name"]

for (let key in myObject) {
  console.log(key); // Väljund: name
}

Sümbol-omadustele juurdepääsemiseks peate kasutama meetodit Object.getOwnPropertySymbols(), mis tagastab massiivi kõigist objekti sümbol-omadustest:

const mySymbol = Symbol("myKey");
const myObject = {
  name: "My Object",
  [mySymbol]: "Symbol Value"
};

const symbolKeys = Object.getOwnPropertySymbols(myObject);
console.log(symbolKeys); // Väljund: [Symbol(myKey)]
console.log(myObject[symbolKeys[0]]); // Väljund: Symbol Value

Tuntud sümbolid

JavaScript pakub komplekti sisseehitatud sümboleid, mida tuntakse tuntud sümbolitena ja mis esindavad spetsiifilisi käitumisviise või funktsionaalsusi. Need sümbolid on Symbol konstruktori omadused (nt Symbol.iterator, Symbol.toStringTag). Need võimaldavad teil kohandada, kuidas objektid erinevates kontekstides käituvad.

Symbol.iterator

Symbol.iterator on sümbol, mis defineerib objekti vaikeiteraatori. Kui objektil on meetod võtmega Symbol.iterator, muutub see itereeritavaks, mis tähendab, et saate seda kasutada for...of tsüklite ja laialilaotusoperaatoriga (...).

Näide: kohandatud itereeritava objekti loomine

const myCollection = {
  items: [1, 2, 3, 4, 5],
  [Symbol.iterator]: function* () {
    for (let item of this.items) {
      yield item;
    }
  }
};

for (let item of myCollection) {
  console.log(item); // Väljund: 1, 2, 3, 4, 5
}

console.log([...myCollection]); // Väljund: [1, 2, 3, 4, 5]

Selles näites on myCollection objekt, mis rakendab iteraatori protokolli, kasutades Symbol.iterator. Generaatorfunktsioon väljastab (yield) iga elemendi items massiivist, muutes myCollection objekti itereeritavaks.

Symbol.toStringTag

Symbol.toStringTag on sümbol, mis võimaldab teil kohandada objekti string-esitust, kui kutsutakse välja Object.prototype.toString().

Näide: toString() esituse kohandamine

class MyClass {
  get [Symbol.toStringTag]() {
    return 'MyClassInstance';
  }
}

const instance = new MyClass();
console.log(Object.prototype.toString.call(instance)); // Väljund: [object MyClassInstance]

Ilma Symbol.toStringTag-ita oleks väljund [object Object]. See sümbol pakub viisi oma objektidele kirjeldavama string-esituse andmiseks.

Symbol.hasInstance

Symbol.hasInstance on sümbol, mis laseb teil kohandada operaatori instanceof käitumist. Tavaliselt kontrollib instanceof, kas objekti prototüübiahel sisaldab konstruktori prototype omadust. Symbol.hasInstance võimaldab seda käitumist üle kirjutada.

Näide: instanceof kontrolli kohandamine

class MyClass {
  static [Symbol.hasInstance](instance) {
    return Array.isArray(instance);
  }
}

console.log([] instanceof MyClass); // Väljund: true
console.log({} instanceof MyClass); // Väljund: false

Selles näites kontrollib Symbol.hasInstance meetod, kas isend on massiiv. See muudab MyClass-i tegelikult massiivide kontrollijaks, sõltumata tegelikust prototüübiahelast.

Muud tuntud sümbolid

JavaScript defineerib mitmeid teisi tuntud sümboleid, sealhulgas:

Globaalne sümbolite register

Mõnikord on vaja sümboleid jagada rakenduse erinevate osade vahel või isegi erinevate rakenduste vahel. Globaalne sümbolite register pakub mehhanismi sümbolite registreerimiseks ja hankimiseks võtme alusel.

Symbol.for(key)

Meetod Symbol.for(key) kontrollib, kas antud võtmega sümbol eksisteerib globaalses registris. Kui see eksisteerib, tagastab see selle sümboli. Kui seda ei eksisteeri, loob see uue sümboli antud võtmega ja registreerib selle registris.

const globalSymbol1 = Symbol.for("myGlobalSymbol");
const globalSymbol2 = Symbol.for("myGlobalSymbol");

console.log(globalSymbol1 === globalSymbol2); // Väljund: true
console.log(Symbol.keyFor(globalSymbol1)); // Väljund: myGlobalSymbol

Symbol.keyFor(symbol)

Meetod Symbol.keyFor(symbol) tagastab võtme, mis on seotud sümboliga globaalses registris. Kui sümbolit registris ei ole, tagastab see undefined.

const mySymbol = Symbol("localSymbol");
console.log(Symbol.keyFor(mySymbol)); // Väljund: undefined

const globalSymbol = Symbol.for("myGlobalSymbol");
console.log(Symbol.keyFor(globalSymbol)); // Väljund: myGlobalSymbol

Oluline: Sümbolid, mis on loodud Symbol() abil, *ei ole* automaatselt globaalsesse registrisse registreeritud. Ainult sümbolid, mis on loodud (või hangitud) Symbol.for() abil, on registri osa.

Praktilised näited ja kasutusjuhud

Siin on mõned praktilised näited, mis demonstreerivad, kuidas sümboleid saab kasutada reaalsetes stsenaariumides:

1. Plugin-süsteemide loomine

Sümboleid saab kasutada plugin-süsteemide loomiseks, kus erinevad moodulid saavad laiendada põhilise objekti funktsionaalsust, ilma et nad satuksid konflikti üksteise omadustega.

// Põhiobjekt
const coreObject = {
  name: "Core Object",
  version: "1.0"
};

// Plugin 1
const plugin1Key = Symbol("plugin1");
coreObject[plugin1Key] = {
  description: "Plugin 1 adds extra functionality",
  activate: function() {
    console.log("Plugin 1 activated");
  }
};

// Plugin 2
const plugin2Key = Symbol("plugin2");
coreObject[plugin2Key] = {
  author: "Another Developer",
  init: function() {
    console.log("Plugin 2 initialized");
  }
};

// Pluginitele juurdepääs
console.log(coreObject[plugin1Key].description); // Väljund: Plugin 1 adds extra functionality
coreObject[plugin2Key].init(); // Väljund: Plugin 2 initialized

Selles näites kasutab iga plugin unikaalset sümboli võtit, vältides potentsiaalseid nimekonflikte ja tagades, et pluginad saavad rahulikult koos eksisteerida.

2. Metaandmete lisamine DOM-elementidele

Sümboleid saab kasutada metaandmete lisamiseks DOM-elementidele, segamata nende olemasolevaid atribuute või omadusi.

const element = document.createElement("div");

const dataKey = Symbol("elementData");
element[dataKey] = {
  type: "widget",
  config: {},
  timestamp: Date.now()
};

// Metaandmetele juurdepääs
console.log(element[dataKey].type); // Väljund: widget

See lähenemine hoiab metaandmed eraldi elemendi standardatribuutidest, parandades hooldatavust ja vältides potentsiaalseid konflikte CSS-i või muu JavaScripti koodiga.

3. Privaatsete omaduste implementeerimine

Kuigi JavaScriptil pole tõelisi privaatseid omadusi, saab sümboleid kasutada privaatsuse simuleerimiseks. Kasutades sümbolit omaduse võtmena, saate muuta välise koodi jaoks omadusele juurdepääsu raskeks (kuid mitte võimatuks).

class MyClass {
  #privateSymbol = Symbol("privateData"); // Märkus: See '#' süntaks on *tõeline* privaatne väli, mis võeti kasutusele ES2020-s, ja erineb näitest

  constructor(data) {
    this[this.#privateSymbol] = data;
  }

  getData() {
    return this[this.#privateSymbol];
  }
}

const myInstance = new MyClass("Sensitive Information");
console.log(myInstance.getData()); // Väljund: Sensitive Information

// "Privaatsele" omadusele juurdepääs (raske, kuid võimalik)
const symbolKeys = Object.getOwnPropertySymbols(myInstance);
console.log(myInstance[symbolKeys[0]]); // Väljund: Sensitive Information

Kuigi Object.getOwnPropertySymbols() saab sümboli siiski paljastada, muudab see vähem tõenäoliseks, et väline kood pääseb juhuslikult "privaatsele" omadusele ligi või muudab seda. Märkus: Tõelised privaatsed väljad (kasutades `#` prefiksit) on nüüd saadaval kaasaegses JavaScriptis ja pakuvad tugevamaid privaatsusgarantiisid.

Parimad tavad sümbolite kasutamisel

Siin on mõned parimad tavad, mida sümbolitega töötades meeles pidada:

Kokkuvõte

JavaScripti sümbolid pakuvad võimsat mehhanismi unikaalsete omaduste võtmete loomiseks, metaandmete lisamiseks objektidele ja objektide käitumise kohandamiseks. Mõistes, kuidas sümbolid töötavad ja järgides parimaid tavasid, saate kirjutada robustsemat, hooldatavamat ja konfliktivaba JavaScripti koodi. Olgu tegemist plugin-süsteemide ehitamise, metaandmete lisamisega DOM-elementidele või privaatsete omaduste simuleerimisega, sümbolid on väärtuslik tööriist teie JavaScripti arendustöövoo täiustamiseks.