Descrittori proprietà

È probabile che la maggior parte dell'interazione con le proprietà degli oggetti a livello di superficie, tra cui la creazione di valori letterali oggetto e l'impostazione e l'accesso utilizzando le chiavi. Tuttavia, puoi configurare internamente qualsiasi proprietà un oggetto per un controllo granulare sulla modalità di accesso a tali proprietà, modificati e definiti. Ogni proprietà di un oggetto ha un insieme di attributi invisibili contenente i metadati associati alla proprietà in questione, denominati "proprietà descrittori".

A ogni proprietà sono associati due tipi di descrittori: descrittori di dati e accessori. Un descrittore di dati include coppie chiave-valore che contengono il valore di una proprietà, indipendentemente dal fatto che è scrivibile, configurabile o enumerabile. I descrittori della funzione di accesso contengono funzioni che vengono eseguite quando si imposta, modifica o si accede a una proprietà.

Proprietà Tipo di descrittore Valore predefinito da
Object.defineProperty()
Descrizione
[[Value]] Dati undefined Contiene il valore di una proprietà.
[[Writable]] Dati false Determina se puoi modificare il valore della proprietà.
[[Get]] Funzione di accesso undefined La funzione getter della proprietà, che viene eseguita quando accessibile la proprietà.
[[Set]] Funzione di accesso undefined La funzione setter della proprietà, che viene eseguita quando viene impostata o modificata.
[[Configurable]] Entrambi false Se questo è false, la proprietà non può essere eliminata e i relativi non possono essere modificati. Se è false e [[Writable]] è true, il valore della proprietà può essere ancora modificate.
[[Enumerable]] Entrambi false Se si tratta di true, puoi eseguire l'iterazione della proprietà utilizzando Loop for...in o statica Object.keys() .

Ognuna di queste proprietà utilizza la stessa forma abbreviata di [[Prototype]], per indicare che non è possibile accedere direttamente a queste proprietà. Utilizza invece Object.defineProperty() metodo statico per definire o modificare le proprietà di un . Object.defineProperty() accetta tre argomenti: l'oggetto su cui agire, la chiave di proprietà da creare o modificare e un oggetto contenente descrittori associati alla proprietà che viene creata o modificata.

Per impostazione predefinita, le proprietà create utilizzando Object.defineProperty() non sono scrivibili, enumerabili o configurabili. Tuttavia, qualsiasi proprietà che crei come parte del valore letterale oggetto o utilizzando la notazione punto o parentesi scrivibili, enumerabili e configurabili.

const myObj = {};

Object.defineProperty(myObj, 'myProperty', {
  value: true,
  writable: false
});

myObj.myProperty;
> true

myObj.myProperty = false;

myObj.myProperty;
> true

Ad esempio, quando [[Writable]] ha un valore false, stai tentando di impostare un nuovo valore per la proprietà associata non riesce a controllare in modo silenzioso al di fuori della modalità con restrizioni e genera un Errore in modalità massima:

{
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}
> true

(function () {
    "use strict";
    const myObj = {};

    Object.defineProperty(myObj, 'myProperty', {
    value: true,
    writable: false
    });

    myObj.myProperty = false;
    myObj.myProperty;
}());\
> Uncaught TypeError: "myProperty" is read-only

Fare un uso efficace dei descrittori è un concetto abbastanza avanzato, ma comprendere la struttura interna di un oggetto è essenziale per comprendere le sintassi utilizzate nell'uso degli oggetti nei modi più comuni. Ad esempio: quando si utilizza il metodo statico Object.create(), questi concetti che ti offre un controllo granulare su tutti i prototipi collegati al nuovo .

Object.create() crea un nuovo oggetto utilizzando un oggetto esistente come relativo un prototipo di modello. In questo modo, il nuovo oggetto può ereditare proprietà e metodi da un altro un oggetto definito dall'utente, come gli oggetti ereditano le proprietà Prototipo Object integrato di JavaScript. Quando richiami Object.create() con un oggetto come argomento, crea un oggetto vuoto con l'oggetto passato come del suo prototipo.

const myCustomPrototype = {
  'myInheritedProp': 10
};

const newObject = Object.create( myCustomPrototype );

newObject;
> Object {  }
<prototype>: Object { myInheritedProp: 10 }
  myInheritedProp: 10
  <prototype>: Object { … }

Object.create può prendere un secondo argomento che specifica le proprie proprietà per appena creato utilizzando una sintassi simile a Object.defineProperty(): cioè un oggetto che mappa le chiavi a un insieme di attributi descrittori:

const myCustomPrototype = {
  'myInheritedProp': 10
};

const myObj = Object.create( myCustomPrototype, {
        myProperty: {
            value: "The new property value.",
            writable: true,
            configurable: true
        }
  });

myObj;
> Object { … }
    myProperty: "The new property value."
    <prototype>: Object { myInheritedProp: 10 }

In questo esempio, il nuovo oggetto (myObj) utilizza un valore letterale oggetto (myCustomPrototype) come prototipo, che a sua volta contiene i file Object.prototype, generando una serie di prototipi ereditati chiamati prototipazione. Ogni oggetto ha un prototipo, assegnato o ereditato, che ha un proprio prototipo assegnato o ereditato. Questa catena termina con Prototipo di null, che non dispone di un proprio prototipo.

const myPrototype = {
  'protoProp': 10
};

const newObject = Object.setPrototypeOf( { 'objProp' : true }, myPrototype );

newObject;
> Object { objProp: true }
    objProp: true
    <prototype>: Object { protoProp: 10 }
        protoProp: 10
        <prototype>: Object { … }

Le proprietà contenute nel prototipo di un valore sono disponibili al "livello superiore" di un oggetto, senza dover accedere direttamente alla proprietà prototype:

const objectLiteral = {
    "value" : true
};

objectLiteral;
> Object { value: true }
    value: true
    <prototype>: Object { … }

objectLiteral.toString();
"[object Object]"

Questo schema vale per l'intera catena di prototipi associata a un oggetto: quando tenta di accedere a una proprietà, l'interprete lo cerca proprietà in ogni "livello" della catena del prototipo, dall'alto verso il basso, finché trova la proprietà o termina la catena:

const myCustomPrototype = {
  'protoProp': "Prototype property value."
};

const myObj = Object.create( myCustomPrototype, {
    myProperty: {
        value: "Top-level property value.",
        writable: true,
        configurable: true
    }
});

myObj.protoProp;
> "Prototype property value."

Verifica le tue conoscenze

Quali descrittori sono le funzioni di accesso?

[[Get]]
[[Set]]
[[Writable]]