[ Web Proxy ]
URL:
Viewing: https://it.javascript.info/function-prototype [Back]  [Original]

F.prototype
IT

Vorremo rendere disponibile questo progetto open-source per persone in tutto il mondo.

Aiutaci a tradurre il contenuto di questo tutorial nella tua lingua!

    Cerca in Javascript.info:
    Cerca nel tutorial:
    Light themeDark theme
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek

    Ricordate, nuovi oggetti possono essere creati con un costruttore, come new F().

    Se F.prototype un oggetto, loperatore new si prender cura di impostare [[Prototype]] per il nuovo oggetto.

    Da notare:

    JavaScript supporta la prototypal inheritance fin dallinizio. Fu una delle caratteristiche principali del linguaggio.

    Ma allinizio non cera un accesso diretto. Lunica cosa su cui ci si poteva affidare era la propriet "prototype" del costruttore, descritta in questo capitolo. Per questo, esistono ancora molti script che ne fanno utilizzo.

    Da notare che qui F.prototype , sta per una comune propriet chiamata "prototype" in F. Sembra molto simile al termine prototype, ma in questo caso intendiamo realmente riferirci ad una propriet con questo nome.

    Vediamo qui un esempio:

    let animal = {
      eats: true
    };
    
    function Rabbit(name) {
      this.name = name;
    }
    
    Rabbit.prototype = animal;
    
    let rabbit = new Rabbit("White Rabbit"); //  rabbit.__proto__ == animal
    
    alert( rabbit.eats ); // true

    Impostare Rabbit.prototype = animal fa letteralmente quanto segue: Quando un nuovo new Rabbit viene creato, assegna il suo [[Prototype]] ad animal.

    Questo il risultato:

    []

    In figura, "prototype" una freccia orrizzontale, ci significa che una comune propriet, mentre [[Prototype]] verticale, quindi rabbit eredita da animal.

    F.prototype viene utilizzato solamente al momento in cui si invoca new F

    F.prototype viene utilizzata solamente quando si invoca new F, e si occupa di assegnare [[Prototype]] del nuovo oggetto.

    Se, dopo la creazione, F.prototype cambia (F.prototype = <another object>), allora verr creato un nuovo oggetto con new F che avr un altro oggetto come [[Prototype]], ma gli oggetti gi esistenti faranno riferimento a quello vecchio.

    Default F.prototype, la propriet constructor

    Ogni funzione possiede la propriet "prototype" anche se non gliela forniamo direttamente.

    Il "prototype" di default un oggetto con ununica propriet, il constructor che punta alla funzione stessa.

    Vediamo un esempio:

    function Rabbit() {}
    
    /* default prototype
    Rabbit.prototype = { constructor: Rabbit };
    */
    []

    Possiamo verificarlo:

    function Rabbit() {}
    // di default:
    // Rabbit.prototype = { constructor: Rabbit }
    
    alert( Rabbit.prototype.constructor == Rabbit ); // true

    Naturalmente, se non facciamo nulla, il constructor sar disponibile a tutti i rabbit attraverso [[Prototype]]:

    function Rabbit() {}
    // di default:
    // Rabbit.prototype = { constructor: Rabbit }
    
    let rabbit = new Rabbit(); // eredita da {constructor: Rabbit}
    
    alert(rabbit.constructor == Rabbit); // true (dal prototype)
    []

    Possiamo utilizzare il constructor per creare un nuovo oggetto utilizzando lo stesso costruttore delloggetto gi esistente.

    Come nellesempio:

    function Rabbit(name) {
      this.name = name;
      alert(name);
    }
    
    let rabbit = new Rabbit("White Rabbit");
    
    let rabbit2 = new rabbit.constructor("Black Rabbit");

    Questo torna molto utile quando abbiamo un oggetto, ma non sappiamo quale costruttore stato utilizzato (ad esempio se arriva da una libreria di terze parti), e abbiamo bisogno di crearne un altro dello stesso tipo.

    Ma probabilmente la cosa pi importante del "constructor" che

    JavaScript stesso non garantisce il giusto valore del "constructor".

    E vero, esiste di default nel "prototype" delle funzioni, ma questo tutto. Ci che accade dopo solo nostra responsabilit.

    In particolare, se rimpiazziamo completamente il prototype di default, allora non ci sar alcun "constructor".

    Ad esempio:

    function Rabbit() {}
    Rabbit.prototype = {
      jumps: true
    };
    
    let rabbit = new Rabbit();
    alert(rabbit.constructor === Rabbit); // false

    Quindi, per mantenere il "constructor" corretto, possiamo decidere di aggiungere/rimuovere propriet al "prototype" di default, invece che sovrascriverlo completamente:

    function Rabbit() {}
    
    // Non sovrascriviamo Rabbit.prototype completamente
    // aggiungiamo semplicemente una propriet
    Rabbit.prototype.jumps = true
    // il Rabbit.prototype.constructor viene cosi preservato

    O, in alternativa, possiamo ricreare il constructor manualmente:

    Rabbit.prototype = {
      jumps: true,
      constructor: Rabbit
    };
    
    // ora il costruttore  corretto, perch lo abbiamo aggiunto noi

    Riepilogo

    In questo capitolo abbiamo descritto brevemente il modo in cui impostare il [[Prototype]] per gli oggetti generati tramite il costruttore. Pi avanti vedremo dei pattern pi avanzati su cui fare affidamento.

    Il tutto abbastanza semplice, solo alcune note per renderlo pi chiaro:

    • La propriet F.prototype (da non confondere con [[Prototype]]) imposta [[Prototype]] dei nuovi oggetti quando viene invocato new F().
    • Il valore di F.prototype pu essere sia un oggetto che null: altri valori verranno ignorati.
    • La propriet "prototype" ha un effetto speciale quando impostata in un costruttore, ed invocata con new.

    Negli oggetti comuni la propriet prototype non ha alcun significato speciale:

    let user = {
      name: "John",
      prototype: "Bla-bla" // nessuna magia
    };

    Di default tutte le funzioni hanno F.prototype = { constructor: F }, quindi possiamo ottenere il costruttore di un oggetto accedendo alla sua propriet "constructor".

    Esercizi

    importanza: 5

    Nel codice sotto, andiamo a creare new Rabbit, e successivamente proviamo a modificare il suo prototype.

    Inizialmente, abbiamo questo codice:

    function Rabbit() {}
    Rabbit.prototype = {
      eats: true
    };
    
    let rabbit = new Rabbit();
    
    alert( rabbit.eats ); // true
    1. Aggiungiamo una o pi stringhe. Cosa mostrer alert ora?

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      Rabbit.prototype = {};
      
      alert( rabbit.eats ); // ?
    2. E se il codice come il seguente (abbiamo rimpiazzato una sola riga)?

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      Rabbit.prototype.eats = false;
      
      alert( rabbit.eats ); // ?
    3. E in questo caso (abbiamo rimpiazzato solo una riga)?

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      delete rabbit.eats;
      
      alert( rabbit.eats ); // ?
    4. Lultima variante:

      function Rabbit() {}
      Rabbit.prototype = {
        eats: true
      };
      
      let rabbit = new Rabbit();
      
      delete Rabbit.prototype.eats;
      
      alert( rabbit.eats ); // ?
    soluzione

    Riposte:

    1. true.

      Lassegnazione a Rabbit.prototype imposta [[Prototype]] per i nuovi oggetti, ma non influenza gli oggetti gi esistenti.

    2. false.

      Gli oggetti vengono assegnati per riferimento. Loggetto in Rabbit.prototype non viene duplicato, sempre un oggetto riferito sia da Rabbit.prototype che da [[Prototype]] di rabbit.

      Quindi quando cambiamo il suo contenuto tramite un riferimento, questo sar visibile anche attraverso laltro.

    3. true.

      Tutte le operazion di delete vengono applicate direttamente alloggetto. Qui delete rabbit.eats prova a rimuovere la propriet eats da rabbit, ma non esiste. Quindi loperazione non avr alcun effetto.

    4. undefined.

      La propriet eats viene rimossa da prototype, non esiste pi.

    importanza: 5

    Immagina di avere un oggetto arbitrario obj, creato da un costruttore non sappiamo quale, ma vorremmo poter creare un nuovo oggetto utilizzandolo.

    Possiamo farlo in questo modo?

    let obj2 = new obj.constructor();

    Fornite un esempio di costruttore per obj che permetta a questo codice di funzionare correttamente. Ed un esempio che non lo farebbe funzionare.

    soluzione

    Possiamo utilizzare questo approccio se siamo sicuri che il "constructor" possiede il valore corretto.

    Ad esempio, se non tocchiamo il "prototype" di default, allora il codice funzioner di sicuro:

    function User(name) {
      this.name = name;
    }
    
    let user = new User('John');
    let user2 = new user.constructor('Pete');
    
    alert( user2.name ); // Pete (ha funzionato!)

    Ha funzionato, poich User.prototype.constructor == User.

    Ma se qualcuno, per un qualsiasi motivo, sovrascrivesse User.prototype e dimenticasse di ricreare il constructor di riferimento a User, allora fallirebbe.

    Ad esempio:

    function User(name) {
      this.name = name;
    }
    User.prototype = {}; // (*)
    
    let user = new User('John');
    let user2 = new user.constructor('Pete');
    
    alert( user2.name ); // undefined

    Perch user2.name undefined?

    Ecco come new user.constructor('Pete') funziona:

    1. Prima, controlla se esiste constructor in user. Niente.
    2. Successivamente segue la catena di prototype. Il prototype di user User.prototype, e anche qui non c un constructor (perch ci siamo dimenticati di impostarlo!).
    3. Seguendo la catena, User.prototype un oggetto semplice, il suo prototype Object.prototype.
    4. Infine, per Object.prototype, c Object.prototype.constructor == Object. Quindi verr utilizzato.

    In conclusione, abbiamo let user2 = new Object('Pete').

    Probabilmente, non quello che avremmo voluto, ossia creare new User, non new Object. Questo il risultato del costruttore mancante.

    (Nel caso tu sia curioso, la chiamata new Object(...) converte il suo argomento in un oggetto. Questa una cosa teorica, in pratica nessuno chiama new Object con un valore, e generalmente non usiamo mai new Object per creare oggetti.

    Mappa del tutorial

    Commenti

    leggi questo prima di lasciare un commento
    • Per qualsiasi suggerimento - per favore, apri una issue su GitHub o una pull request, piuttosto di lasciare un commento.
    • Se non riesci a comprendere quanto scitto nell'articolo ti preghiamo di fornire una spiegazione chiara.
    • Per inserire delle righe di codice utilizza il tag <code>, per molte righe includile nel tag <pre>, per pi di 10 righe utilizza una sandbox (plnkr, jsbin, codepen)

    Web Proxy Viewer  |  New URL  |  Original Page