Guida definitiva a getter e setter in JavaScript
Getter e setter sono funzioni o metodi utilizzati per ottenere e impostare i valori delle variabili . Il concetto getter-setter è comune nella programmazione di computer : quasi tutti i linguaggi di programmazione di alto livello sono dotati di una serie di sintassi per implementare getter e setter, incluso JavaScipt.
In questo post vedremo cosa sono i setter dei getter e come crearli e usarli in JavaScript .
Getter-setter e incapsulamento
L'idea di getter e setter è sempre menzionata insieme all'incapsulamento . L'incapsulamento può essere compreso in due modi .
In primo luogo, è l'impostazione del trio di data-getters-setters per accedere e modificare tali dati. Questa definizione è utile quando alcune operazioni, come la convalida, devono essere eseguite sui dati prima di salvarli o visualizzarli. I getter e setter forniscono la casa perfetta per questo.
In secondo luogo, c'è una definizione più rigorosa secondo cui l'incapsulamento è fatto per nascondere i dati, per renderlo inaccessibile da altro codice, tranne che attraverso i getter ei setter . In questo modo non finiremo per sovrascrivere accidentalmente dati importanti con qualche altro codice nel programma.
Crea getter e setter
1. Con metodi
Poiché i getter e i setter sono fondamentalmente delle funzioni che recuperano / modificano un valore, esistono più modi per crearli e usarli. Il primo modo è:
var obj = {foo: 'questo è il valore di foo', getFoo: function () {return this.foo; }, setFoo: function (val) {this.foo = val; }} console.log (obj.getFoo ()); // "questo è il valore di foo" obj.setFoo ('hello'); console.log (obj.getFoo ()); // "Ciao"
Questo è il modo più semplice per creare getter e setter. C'è una proprietà foo
e ci sono due metodi: getFoo
e setFoo
per restituire e assegnare un valore a quella proprietà.
2. Con parole chiave
Un modo più "ufficiale" e robusto per creare getter e setter è utilizzare le parole chiave get
e set
.
Per creare un getter, posizionare la parola chiave get
davanti a una dichiarazione di funzione che fungerà da metodo getter e utilizzare la parola chiave set
nello stesso modo per creare un setter . La sintassi è la seguente:
var obj = {fooVal: 'questo è il valore di foo', get foo () {return this.fooVal; }, imposta foo (val) {this.fooVal = val; }} console.log (obj.foo); // "questo è il valore di foo" obj.foo = 'hello'; console.log (obj.foo); // "Ciao"
Si noti che i dati possono essere memorizzati solo con un nome di proprietà ( fooVal
) diverso dal nome dei metodi getter-setter ( foo
) perché una proprietà che trattiene il getter-setter non può contenere anche i dati .
Qual è il modo migliore?
Se si sceglie di creare getter e setter con parole chiave, è possibile utilizzare l' operatore di assegnazione per impostare i dati e l' operatore punto per ottenere i dati, allo stesso modo in cui si accederà / imposterà il valore di una proprietà normale.
Tuttavia, se si sceglie il primo modo di codificare getter e setter, è necessario chiamare i metodi setter e getter utilizzando la sintassi di chiamata della funzione perché sono funzioni tipiche (niente di speciale come quelli creati utilizzando le parole chiave get
e set
).
Inoltre, c'è la possibilità che tu possa finire per assegnare casualmente qualche altro valore alle proprietà che hanno mantenuto quei metodi getter-setter e perderli completamente ! Qualcosa di cui non devi preoccuparti nel metodo successivo.
Quindi, puoi capire perché ho detto che la seconda tecnica è più robusta .
Sovrascrivi la prevenzione
Se per qualche motivo preferisci la prima tecnica, fai in modo che le proprietà Object.defineProperties
metodi getter-setter in sola lettura, creando loro usando Object.defineProperties
. Le proprietà create tramite Object.defineProperties
, Object.defineProperty
e Reflect.defineProperty
si configurano automaticamente in writable: false
che significa sola lettura :
/ * Prevenzione della sovrascrittura * / var obj = {pippo: 'questo è il valore di foo'}; Object.defineProperties (obj, {'getFoo': {valore: function () {return this.foo;}}, 'setFoo': {valore: function (val) {this.foo = val;}}}); obj.getFoo = 66; // getFoo non verrà sovrascritto! console.log (obj.getFoo ()); // "questo è il valore di foo"
Operazioni all'interno di getter e setter
Una volta introdotti i getter e i setter, è possibile procedere ed eseguire operazioni sui dati prima di modificarli o restituirli.
Nel codice sottostante, nella funzione getter i dati sono concatenati con una stringa prima di essere restituiti, e nella funzione setter viene eseguita una convalida se il valore è un numero o meno prima dell'aggiornamento n
.
var obj = {n: 67, get id () {return 'L'ID è:' + this.n; }, imposta id (val) {if (typeof val === 'number') this.n = val; }} console.log (obj.id); // "L'ID è: 67" obj.id = 893; console.log (obj.id); // "L'ID è: 893" obj.id = 'hello'; console.log (obj.id); // "L'ID è: 893"
Proteggi i dati con getter e setter
Finora, abbiamo coperto l'uso di getter e setter nel primo contesto dell'incapsulamento. Passiamo al secondo, ovvero come nascondere i dati dal codice esterno con l'aiuto di getter e setter.
Dati non protetti
L'impostazione di getter e setter non significa che i dati possano essere consultati e modificati solo tramite tali metodi. Nell'esempio seguente, è cambiato direttamente senza toccare i metodi getter e setter:
var obj = {fooVal: 'questo è il valore di foo', get foo () {return this.fooVal; }, imposta foo (val) {this.fooVal = val; }} obj.fooVal = 'hello'; console.log (obj.foo); // "Ciao"
Non abbiamo usato il setter ma modificato direttamente i dati ( fooVal
) . I dati inizialmente impostati in obj
sono più disponibili! Per evitare che ciò accada (accidentalmente), hai bisogno di protezione per i tuoi dati. Puoi aggiungerlo limitando la portata di dove i tuoi dati sono disponibili. Puoi farlo sia con l' ambito del blocco che con l' ambito della funzione .
1. Ambito del blocco
Un modo è utilizzare un ambito di blocco all'interno del quale verranno definiti i dati utilizzando la parola chiave let
che ne limita l'ambito a quel blocco.
È possibile creare un ambito di blocco inserendo il codice all'interno di un paio di parentesi graffe . Ogni volta che crei un ambito di blocco, assicurati di lasciare un commento sopra di esso chiedendo che le parentesi siano lasciate da sole, in modo che nessuno rimuova le parentesi per errore pensando di essere un paio di parentesi ridondanti nel codice o aggiungere un'etichetta all'ambito del blocco .
/ * BLOCK SCOPE, lascia le parentesi! * / {let fooVal = 'questo è il valore di foo'; var obj = {get foo () {return fooVal; }, set foo (val) {fooVal = val}}} fooVal = 'hello'; // non intaccherà il fooVal all'interno del blocco console.log (obj.foo); // "questo è il valore di foo"
La modifica / creazione di fooVal
al di fuori del blocco non influirà sul fooVal
riferito ai setter dei getter.
2. Scopo della funzione
Il modo più comune per proteggere i dati con l'ambito è mantenere i dati all'interno di una funzione e restituire un oggetto con getter e setter da quella funzione.
function myobj () {var fooVal = 'questo è il valore di foo'; return {get foo () {return fooVal; }, set foo (val) {fooVal = val}}} fooVal = 'hello'; // non influenzerà il nostro originale fooVal var obj = myobj (); console.log (obj.foo); // "questo è il valore di foo"
L'oggetto (con il foo()
getter-setter al suo interno) restituito dalla funzione myobj()
viene salvato in obj
, e quindi obj
viene usato per chiamare getter e setter .
3. Protezione dei dati senza ambito
C'è anche un altro modo per proteggere i tuoi dati dalla sovrascrittura senza limitarne l'ambito . La logica dietro è così: come puoi cambiare un dato se non sai come si chiama?
Se i dati hanno un nome di variabile / proprietà non facilmente riproducibile, è probabile che nessuno (nemmeno noi stessi) finirà per sovrascriverlo assegnando un valore a quella variabile / nome della proprietà.
var obj = {s89274934764: 'questo è il valore di foo', get foo () {return this.s89274934764; }, imposta foo (val) {this.s89274934764 = val; }} console.log (obj.foo); // "questo è il valore di foo"
Vedi, questo è un modo per risolvere le cose. Anche se il nome che ho scelto non è molto buono, puoi anche usare valori o simboli casuali per creare nomi di proprietà come proposto da Derick Bailey in questo post del blog. L'obiettivo principale è mantenere i dati nascosti da un altro codice e lasciare che una coppia getter-setter acceda / aggiorni.
Quando dovresti usare getter e setter?
Ora arriva la grande domanda: inizi ad assegnare getter e setter a tutti i tuoi dati ora?
Se stai nascondendo i dati, non c'è altra scelta .
Ma se i tuoi dati sono visti da un altro codice va bene, hai ancora bisogno di usare getter setter solo per legarlo con il codice che esegue alcune operazioni su di esso? Direi di si. Il codice si somma molto presto . La creazione di micro unità di dati individuali con il proprio getter-setter fornisce una certa indipendenza per lavorare su tali dati senza intaccare altre parti del codice.
Crea il tuo URL shortener con Polr
Gli shortener di URL Mainstream come Bit.ly sono grandiosi ma difficili da personalizzare. Le loro API possono essere limitanti, e mentre sono perfette per la maggior parte dei progetti più piccoli, a loro manca quel certo fascino di un URL shortener unico.Polr è un'API shortener URL open source gratuita che puoi installare ed eseguire localmente sul tuo dominio.
Betty: Trasforma l'inglese generico nei comandi del terminale Linux
Il terminale Linux può essere una bestia complessa e sarebbe utile avere qualcosa come Siri per semplificare le cose. Certo, non c'è spesso bisogno di entrare nel terminale per utenti regolari, ma ci sono alcuni vantaggi nell'usare il terminale attraverso l'interfaccia grafica . Puoi fare molte cose con il terminale che non sono facili da fare nelle interfacce utente grafiche - inoltre, c'è solo questo strano piacere nerd nel fare il più possibile da un'interfaccia a linea di comando.Aff