Skip to content

5. Gli oggetti letterali

Con il termine «oggetti letterali» si indicano qui gli oggetti definiti letteralmente nel codice. JavaScript prevede il concetto di classe e di oggetto istanza di classe. Non è quindi di questo tipo di oggetto che stiamo parlando ora.

Image

5.1. script [obj-01]

Qui presentiamo le prime proprietà degli oggetti letterali. La principale è che l’oggetto viene gestito tramite un puntatore.


'use strict';
// un oggetto vuoto
const obj1={};
// è possibile creare dinamicamente le proprietà dell'oggetto
obj1.prop1="abcd";
console.log('obj1=',obj1);
// altra proprietà
obj1.prop2=[1,2,3];
console.log("obj1=",obj1);
// altra proprietà con una notazione diversa
obj1['prop3']=true;
console.log("obj1=",obj1);
// obj1 è un riferimento all'oggetto (puntatore), non l'oggetto stesso
const obj2=obj1;
// obj2 e obj1 puntano allo stesso oggetto
obj2.prop1="xyzt";
console.log("obj1=",obj1);
console.log("obj2=",obj2);
// le proprietà possono essere variabili
const var1='prop1';
console.log('prop1=',obj1[var1]);

Esecuzione


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\objets\obj-01.js"
obj1=[object Object]
obj1= { prop1: 'abcd', prop2: [ 1, 2, 3 ] }
obj1= { prop1: 'abcd', prop2: [ 1, 2, 3 ], prop3: true }
obj1= { prop1: 'xyzt', prop2: [ 1, 2, 3 ], prop3: true }
obj2= { prop1: 'xyzt', prop2: [ 1, 2, 3 ], prop3: true }
prop1= xyzt

Commenti

  • riga 3 del codice: un oggetto viene gestito tramite un puntatore. Quindi [obj1] è un puntatore. Modificare l'oggetto puntato non modifica il puntatore [obj1]. Ecco perché, come per gli array, viene dichiarato un riferimento a un oggetto con la parola chiave [const];
  • riga 6 del codice: come per gli array, [console.log] è in grado di visualizzare oggetti;
  • riga 11 del codice: obj1.prop3 può essere riscritto come obj1.[‘prop3’]. Quest’ultima notazione è utile quando “prop3” è in realtà una variabile (righe 20-21);
  • righe 13-18 del codice: mostrano che l’istruzione [obj2=obj1] è una copia per riferimento dell’oggetto e non dell’oggetto stesso;

5.2. script [obj-02]

Questo script mostra che le proprietà di un oggetto possono avere come valore un oggetto. Si ottengono così oggetti multilivello. Viene inoltre introdotto l’oggetto globale [JSON] che consente di effettuare conversioni oggetto ↔ stringa di caratteri.


''use strict';
// un oggetto a più livelli
const personne = {
  prénom: "martin",
  âge: 12,
  père: {
    prénom: "paul",
    âge: 45
  },
  mère: {
    prénom: "micheline",
    âge: 42
  }
}
// accesso alle proprietà
console.log("prénom personne=", personne.prénom);
console.log("prénom mère=", personne.mère.prénom);
personne.mère.âge = 40;
console.log("âge mère=", personne.mère.âge);
// console.log è in grado di visualizzare gli oggetti
console.log("personne=", personne);
console.log("mère=", personne.mère);
// è anche possibile visualizzare la stringa jSON dell'oggetto
let json = JSON.stringify(personne);
console.log("jSON=", json);
// è possibile rileggere il jSON
let personne2 = JSON.parse(json);
console.log("père=", personne2.père);

Commenti

  • riga 24: trasformazione di un oggetto JavaScript in stringa jSON;
  • riga 27: trasformazione di una stringa jSON in oggetto JavaScript;

Esecuzione


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\objets\obj-02.js"
prénom personne= martin
prénom mère= micheline
âge mère= 40
personne= { 'prénom': 'martin',
'età': 12,
'padre': { 'nome': 'paul', 'età': 45 },
'madre': { 'nome': 'micheline', 'età': 40 } }
mère= { 'prénom': 'micheline', 'âge': 40 }
jSON= {"prénom":"martin","âge":12,"père":{"prénom":"paul","âge":45},"mère":{"prénom":"micheline","âge":40}}
père= { 'prénom': 'paul', 'âge': 45 }

Commenti

  • riga 10: in una stringa jSON, le proprietà devono essere racchiuse tra virgolette, così come i valori di tipo stringa di caratteri;

5.3. script [obj-03]

Questo script introduce il concetto di getter/setter di una proprietà di un oggetto:


'use strict';
// getter e setter di un oggetto
const personne = {
  // getter
  get nom() {
    console.log("getter nom");
    return this._nom;
  },
  // setter
  set nom(unNom) {
    console.log("setter nom");
    this._nom = unNom;
  }
};
// setter
personne.nom = "Hercule";
// getter
console.log(personne.nom);
// l'oggetto stesso
console.log("personne=", personne);
// ciò non impedisce di accedere direttamente alla proprietà [_nom]
personne._nom = "xyz";
console.log("personne=", personne);

Commenti

  • righe 5-7: definizione di una funzione [getter], che in genere restituisce il valore di una proprietà dell’oggetto ma che in realtà può restituire qualsiasi cosa. La parola chiave [function] è sostituita dalla parola chiave [get];
  • riga 7: il getter restituisce la proprietà [_nom]. Si nota che questa non necessita di essere dichiarata;
  • righe 10-13: definizione di [setter], una funzione che in genere assegna il valore ricevuto a una proprietà dell’oggetto, ma che in realtà può fare qualsiasi cosa. La parola chiave [function] viene sostituita dalla parola chiave [set]. La funzione [setter] può essere utilizzata per verificare la validità del valore passato come parametro alla funzione [setter];
  • riga 16: la funzione [set nom] verrà chiamata implicitamente;
  • riga 18: la funzione [get nom] verrà chiamata implicitamente;
  • riga 22: mostra che l’utilizzo dei getter/setter dipende dalla discrezione dello sviluppatore. Se quest’ultimo conosce il nome della proprietà gestita da essi, può accedervi direttamente;

Esecuzione


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\objets\obj-03.js"
setter nom
getter nom
Hercule
personne= { nom: [Getter/Setter], _nom: 'Hercule' }
personne= { nom: [Getter/Setter], _nom: 'xyz' }

Si noti, alle righe 5-6, che [console.log] visualizza anche le proprietà che sono funzioni.

5.4. script [obj-04]

Questo script mostra tre modi per scrivere i nomi delle proprietà di un oggetto e due modi per accedervi.


'use strict';
// i nomi delle proprietà di un oggetto  possono essere letterali [nom], racchiusi tra apostrofi ['nom']
// oppure tra virgolette ["nom"]

// letterali
const obj1 = {
  nom: "martin",
  prénom: "jean"
};
console.log("prénom=", obj1.prénom);

// racchiusi tra apostrofi
const obj2 = {
  'nome': "martin",
  'cognome': "jean"
};
console.log("nom=", obj2.nom);

// racchiusi tra virgolette
const obj3 = {
  "nom": "martin",
  "prénom": "jean"
};

// due sintassi possibili per accedere alla proprietà [nom]
console.log("nom=", obj3.nom);
console.log("nom=", obj3['nom']);

Esecuzione


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\objets\obj-04.js"
prénom= jean
nom= martin
nom= martin
nom= martin

5.5. script [obj-05]

Lo script mostra che le proprietà di un oggetto letterale possono essere funzioni. Ci si avvicina quindi molto all'oggetto istanza di classe, in cui sono presenti proprietà e metodi.


'use strict';

// un oggetto può avere proprietà di tipo [function]
const personne = {
  // proprietà
  prénom: "martin",
  âge: 12,
  père: {
    prénom: "paul",
    âge: 45
  },
  mère: {
    prénom: "micheline",
    âge: 42
  },
  // metodo
  toString: function () {
    return JSON.stringify(this);
  }
}

// utilizzo
console.log("personne=", personne);
console.log("personne.toString=", personne.toString());
  • righe 17-19: un metodo interno all’oggetto. In esso, si accede alle proprietà dell’oggetto tramite la parola chiave [this] (riga 18). [this] indica l’oggetto stesso, [this.prénom] indica la proprietà [prénom] di quest’ultimo;

Esecuzione


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\objets\obj-05.js"
personne= { 'prénom': 'martin',
'età': 12,
'padre': { 'nome': 'paul', 'età': 45 },
'madre': { 'nome': 'micheline', 'età': 42 },
toString: [Function: toString] }
personne.toString= {"prénom":"martin","âge":12,"père":{"prénom":"paul","âge":45},"mère":{"prénom":"micheline","âge":42}}

5.6. script [obj-06]

Questo script mostra come accedere alle proprietà di un oggetto quando non se ne conosce a priori il nome.


'use strict';

// un oggetto può avere proprietà di tipo [function]
let personne = {
  // proprietà
  prénom: "martin",
  âge: 12,
  père: {
    prénom: "paul",
    âge: 45
  },
  mère: {
    prénom: "micheline",
    âge: 42
  },
  // metodo
  toString: function () {
    return JSON.stringify(this);
  }
}

// utilizzo
console.log(personne);
// proprietà
console.log("-----------------------");
for (const key in personne) {
  if (personne.hasOwnProperty(key)) {
    const element = personne[key];
    console.log(key, "=", element);
  }
}
// per evitare l'avviso di eslint (1)
console.log("-----------------------");
for (const key in personne) {
  if (Object.prototype.hasOwnProperty.call(personne, key)) {
    const element = personne[key];
    console.log(key, "=", element);
  }
}
// per evitare l'avviso di ESLint (2)
console.log("-----------------------");
for (const key in personne) {
  // eslint-disable-next-line no-prototype-builtins
  if (personne.hasOwnProperty(key)) {
    const element = personne[key];
    console.log(key, "=", element);
  }
}

Commenti

  • righe 26-31: il codice che consente di ottenere l’elenco delle proprietà, esclusi i metodi, di un oggetto. Questo codice è oggetto di un avviso di ESLint:

Image

  • righe 32-39: il codice che consente di aggirare l’avviso ESLint. Si passa attraverso il prototipo della classe [Object];
  • righe 41-47: oppure ci si limita a disattivare l'avviso (riga 43);

5.7. script [obj-07]

Lo script [obj-07] mostra la possibilità di destrutturare un oggetto:


'use strict';
// destrutturazione

// letterali
const obj1 = {
  nom: "martin",
  prénom: "jean"
};

// destrutturazione di obj1 nelle variabili [n,p]
const { nom: n, prénom: p } = obj1;
console.log("n=", n, "p=", p);

// destrutturazione di obj1 nelle variabili [n2,p2]
function f({ nom: n2, prénom: p2 }) {
  console.log("f-n2=", n2, "f-p2=", p2);
}
f(obj1);

// destrutturazione di obj1 nelle variabili [nom,prénom]
function g({ nom: nom, prénom: prénom }) {
  console.log("g-nom=", nom, "g-prénom=", prénom);
}
g(obj1);

// destrutturazione di obj1 nelle variabili [nom,prénom]
// con notazione abbreviata equivalente a h({cognome:cognome,nome:nome})
function h({ nom, prénom }) {
  console.log("h-nom=", nom, "h-prénom=", prénom);
}
h(obj1);

Commenti

  • riga 11: sono le parentesi graffe {} che consentono la destrutturazione. La sintassi

const { nom: n, prénom: p } = obj1

crea due variabili, [n] e [p], ed è equivalente a:


const n = obj1.nom
const p = obj1.prénom

La dichiarazione potrebbe essere la seguente:


const { nom => n, prénom => p } = obj1

per ricordare che i valori degli attributi [nom, prénom] vengono assegnati alle variabili [n, p];

  • l’operazione di destrutturazione si ripete alle righe 15, 21 e 28. Ogni volta, è la presenza delle parentesi graffe {} a indicare che ci sarà una destrutturazione di un oggetto nelle variabili;
  • la riga 28 può risultare sconcertante. Si tratta di una scorciatoia per la notazione:

function h({ nom : nom, prénom : prénom })

I risultati dell’esecuzione sono i seguenti:

1
2
3
4
n= martin p= jean
f-n2= martin f-p2= jean
g-nom= martin g-prénom= jean
h-nom= martin h-prénom= jean

5.8. script [obj-08]

Lo script [obj-08] mostra come ottenere una copia di un oggetto:


'use strict'

// clonazione di oggetti
const obj1 = {
  nom: "martin",
  prénom: "jean"
};

// clona (copia) obj1 con l'operatore spread
const obj2 = { ...obj1 }

// verifiche
// obj2 punta a una copia di obj1
console.log("obj2===obj1 :", obj1 === obj2)
console.log("obj2=", obj2)
  • riga 10: l'operazione di copia dell'oggetto [obj1]. L'operatore ... è chiamato operatore di spread;

I risultati dell’esecuzione sono i seguenti:

obj2===obj1 : false
obj2= { nom: 'martin', 'prénom': 'jean' }
  • riga 1: mostra che i riferimenti [obj1] e [obj2] non puntano allo stesso oggetto;
  • riga 2: mostra che l’oggetto a cui punta [obj2] è una copia dell’oggetto a cui punta [obj1];

5.9. Conclusion

Gli script di questa sezione hanno dimostrato che l’oggetto letterale di JavaScript è simile all’oggetto istanza di classe dei linguaggi orientati agli oggetti. È possibile definirvi proprietà, metodi e getter/setter. Si tratta di un oggetto dinamico le cui proprietà possono essere definite in fase di esecuzione. Si comporta quindi come un dizionario i cui elementi possono essere di qualsiasi tipo, in particolare di tipo [fonction].