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

Metodi degli oggetti,"this"
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

    Metodi degli oggetti,"this"

    Gli oggetti solitamente vengono creati per rappresentare entit del mondo reale, come utenti, prodotti e molto altro:

    let user = {
      name: "John",
      age: 30
    };

    Inoltre, nel mondo reale, un utente pu agire: selezionare qualcosa dalla lista degli acquisti, effettuare login, logout etc.

    In JavaScript le azioni vengono rappresentate tramite le funzioni.

    Esempio di un metodo

    Per iniziare, insegniamo a user a salutare:

    let user = {
      name: "John",
      age: 30
    };
    
    user.sayHi = function() {
      alert("Hello!");
    };
    
    user.sayHi(); // Hello!

    Qui abbiamo appena utilizzato unespressione di funzione per creare una funzione ed assegnarla alla propriet user.sayHi delloggetto.

    Successivamente possiamo chiamarla. Ora lutente pu parlare!

    Una funzione che una propriet di un oggetto si chiama metodo.

    Quindi, nellesempio abbiamo un metodo sayHi delloggetto user.

    Ovviamente possiamo utilizzare una funzione gi dichiarata come metodo:

    let user = {
      // ...
    };
    
    // prima la dichiariamo
    function sayHi() {
      alert("Hello!");
    };
    
    // poi la aggiungiamo come metodo
    user.sayHi = sayHi;
    
    user.sayHi(); // Hello!
    Programmazione orientata agli oggetti

    Quando scriviamo codice utilizzando gli oggetti per rappresentare le entit, questa viene definita programmazione orientata agli oggetti, in breve: OOP.

    OOP una grande cosa, un ambito di interesse con i propri studi. Come scegliere le giuste entit? Come organizzare le interazioni tra loro? Questa larchitettura di un codice, e ci sono molti libri importanti che trattano questo argomento, come Design Patterns: Elements of Reusable Object-Oriented Software di E.Gamma, R.Helm, R.Johnson, J.Vissides oppure Object-Oriented Analysis and Design with Applications di G.Booch, e molti altri.

    La forma breve dei metodi

    Esiste una sintassi pi breve per i metodi in un oggetto letterale:

    // questi oggetti fanno la stessa cosa
    
    user = {
      sayHi: function() {
        alert("Hello");
      }
    };
    
    // la sintassi pi breve risulta pi carina
    user = {
      sayHi() { // equivalente a "sayHi: function(){...}"
        alert("Hello");
      }
    };

    Come possiamo notare, si pu omettere "function" e scrivere solamente sayHi().

    A dire la verit, la notazione non proprio uguale. Ci sono delle sottili differenze legate allereditariet degli oggetti (le studieremo pi avanti), ma per ora non hanno importanza. Nella maggior parte dei casi la forma breve viene preferita.

    this nei metodi

    E molto comune che, per eseguire determinate azioni, un metodo abbia necessit di accedere alle informazioni memorizzate nelloggetto.

    Ad esempio, il codice dentro user.sayHi() potrebbe aver bisogno del nome delluser.

    Per accedere alloggetto, un metodo pu utilizzare la parola chiave this.

    Il valore di this loggetto prima del punto, quello che ha eseguito la chiamata del metodo.

    Ad esempio:

    let user = {
      name: "John",
      age: 30,
    
      sayHi() {
        // "this" is the "current object"
        alert(this.name);
      }
    
    };
    
    user.sayHi(); // John

    In fase di esecuzione, quando viene chiamato il metodo user.sayHi(), il valore di this sar user.

    Tecnicamente, possibile accedere alloggetto anche senza this; lo si fa tramite riferimento alla variabile esterna:

    let user = {
      name: "John",
      age: 30,
    
      sayHi() {
        alert(user.name); // "user" piuttosto di "this"
      }
    
    };

    Questo codice instabile. Se decidessimo di copiare user in unaltra variabile, ad esempio admin = user e sovrascrivere user con qualcosaltro, verrebbe allora effettuato laccesso alloggetto sbagliato.

    Dimostriamolo:

    let user = {
      name: "John",
      age: 30,
    
      sayHi() {
        alert( user.name ); // porta ad un errore
      }
    
    };
    
    
    let admin = user;
    user = null; // sovrascriviamo per rendere tutto pi ovvio
    
    admin.sayHi(); // Errore: non possiamo leggere la propriet 'name' di null

    Se scriviamo this.name piuttosto di user.name allinterno di alert, il codice funzioner.

    this non ha limiti

    In JavaScript, la parola chiave this si comporta diversamente da come fa in molti altri linguaggi di programmazione. Essa pu essere usata in qualsiasi funzione, anche se non si tratta del metodo di un oggetto.

    Non c alcun errore di sintassi in un codice come questo:

    function sayHi() {
      alert( this.name );
    }

    Il valore di this viene valutato al momento dellesecuzione. E pu essere un valore qualsiasi.

    Ad esempio, la stessa funzione potrebbe avere diversi this quando viene chiamata da oggetti diversi:

    let user = { name: "John" };
    let admin = { name: "Admin" };
    
    function sayHi() {
      alert( this.name );
    }
    
    // utilizziamo la stessa funzione su due oggetti
    user.f = sayHi;
    admin.f = sayHi;
    
    // queste chiamate hanno un this diverso
    // "this" all'interno della funzione  riferito all'oggetto "prima del punto"
    user.f(); // John  (this == user)
    admin.f(); // Admin  (this == admin)
    
    admin['f'](); // Admin (il punto o le parentesi quadre forniscono entrambi accesso ai metodi - non c' differenza)

    La regola semplice: se viene chiamato obj.f(), allora, durante la chiamata di f, this si riferisce a obj. Nellesempio sopra assume il valore sia di user che di admin.

    Invocazione senza un oggetto: this == undefined

    Possiamo anche chiamare la funzione senza un oggetto:

    function sayHi() {
      alert(this);
    }
    
    sayHi(); // undefined

    In questo caso this undefined in modalit strict. Se tentiamo di accedere a this.name, ci sar un errore.

    Se non attiva la modalit strict il valore di this in questo caso sar loggetto globale (window in un browser, lo studieremo pi avanti nel capitolo Oggetto globale). Questo strano comportamento ha delle motivazioni storiche, che "use strict" risolve.

    Solitamente questo tipo di chiamate significano un errore di programmazione. Se c un this allinterno di una funzione, ci si aspetta che sia chiamato da un oggetto.

    Le conseguenze della libert di this

    Se avete utilizzato altri linguaggi di programmazione, probabilmente sarete abituati allidea di un this limitato: quando viene definito un metodo in un oggetto, questo avr sempre in this il riferimento alloggetto.

    In JavaScript this libero, il suo valore viene calcolato durante lesecuzione e non dipende da dove il metodo stato definito, ma piuttosto dalloggetto prima del punto.

    Il concetto di valutare this durante lesecuzione ha i suoi pregi e difetti. Da una parte una funzione pu essere riutilizzata per oggetti diversi, dallaltra questa grande flessibilit pu essere fonte di molti errori.

    Il nostro scopo non di giudicare se questa caratteristica del linguaggio sia buona o cattiva, ma di capire come lavorare con essa sfruttandone i benefici ed evitando i problemi.

    Le arrow functions non hanno this

    Ad esempio, qui arrow() usa this preso dal metodo esterno user.sayHi():

    let user = {
      firstName: "Ilya",
      sayHi() {
        let arrow = () => alert(this.firstName);
        arrow();
      }
    };
    
    user.sayHi(); // Ilya

    Questa una speciale caratteristica delle arrow functions; utile quando non vogliamo avere un ulteriore this, ma utilizzare quello del contesto esterno. Pi avanti nel capitolo Arrow functions rivisitate studieremo pi in dettaglio le arrow functions.

    Riepilogo

    • Le funzioni che vengono memorizzate come propriet di un oggetto vengono dette metodi.
    • I metodi consentono agli oggetti di agire, come object.doSomething().
    • I metodi possono riferirsi alloggetto tramite this.

    Il valore this viene definito durante lesecuzione (run-time).

    • Quando una funzione viene dichiarata, pu utilizzare this, ma questo this non avr alcun valore fino a che la funzione non verr chiamata.
    • Una funzione pu essere copiata in vari oggetti.
    • Quando una funzione viene chiamata come metodo: object.method(), il valore di this durante la chiamata si riferisce a object.

    Da notare che le arrow functions sono speciali: non hanno this. Quando si prova ad accedere a this in una funzione freccia, questo verr preso dal contesto esterno.

    Esercizi

    importanza: 5

    Qui la funzione makeUser ritorna un oggetto.

    Qual il risultato dellaccesso a ref? Perch?

    function makeUser() {
      return {
        name: "John",
        ref: this
      };
    }
    
    let user = makeUser();
    
    alert( user.ref.name ); //Qual  il risultato?
    soluzione

    Risposta: un errore.

    Provate:

    function makeUser() {
      return {
        name: "John",
        ref: this
      };
    }
    
    let user = makeUser();
    
    alert( user.ref.name ); // Error: Cannot read property 'name' of undefined

    Questo avviene perch le regole che impostano this non guardano agli oggetti letterali.

    Qui il valore di this dentro makeUser() undefined, perch viene chiamato dentro una funzione, non un metodo.

    Gli oggetti letterali non hanno alcun effetto su this. Il valore di this unico per tutta la funzione, quindi i blocchi di codice e gli oggetti letterali che vi si trovano dentro non hanno alcuna importanza.

    Quindi ref: this prende il this della funzione.

    Possiamo riscrivere la funzione e ritornare lo stesso this con valore undefined:

    function makeUser(){
      return this; // questa volta non c'e' un oggetto letterale
    }
    
    alert( makeUser().name ); // Error: Cannot read property 'name' of undefined

    Come possiamo vedere, il risultato di alert( makeUser().name ) lo stesso di alert( user.ref.name ) nellesempio precedente.

    Qui abbiamo il caso opposto:

    function makeUser() {
      return {
        name: "John",
        ref() {
          return this;
        }
      };
    }
    
    let user = makeUser();
    
    alert( user.ref().name ); // John

    Ora funziona, perch user.ref() un metodo. E il valore di this si riferisce alloggetto prima del punto ..

    importanza: 5

    Create un oggetto calculator con tre metodi:

    • read() richiede tramite prompt due valori e li salva come propriet delloggetto.
    • sum() ritorna la somma dei valori salvati.
    • mul() moltiplica i valori salvati e ritorna il risultato.
    let calculator = {
      // ... your code ...
    };
    
    calculator.read();
    alert( calculator.sum() );
    alert( calculator.mul() );

    Esegui la demo

    Apri una sandbox con i test.

    soluzione
    let calculator = {
      sum() {
        return this.a + this.b;
      },
    
      mul() {
        return this.a * this.b;
      },
    
      read() {
        this.a = +prompt('a?', 0);
        this.b = +prompt('b?', 0);
      }
    };
    
    calculator.read();
    alert( calculator.sum() );
    alert( calculator.mul() );

    Apri la soluzione con i test in una sandbox.

    importanza: 2

    Qui abbiamo un oggetto ladder che ci consente di salire e scendere:

    let ladder = {
      step: 0,
      up() {
        this.step++;
      },
      down() {
        this.step--;
      },
      showStep: function() { // shows the current step
        alert( this.step );
      }
    };

    Ora, se abbiamo bisogno di eseguire pi chiamate in sequenza, possiamo:

    ladder.up();
    ladder.up();
    ladder.down();
    ladder.showStep(); // 1
    ladder.down();
    ladder.showStep(); // 0

    Modificare il codice di up, down e showStep per rendere le chiamate concatenabili, come in questo esempio:

    ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0

    Questo approccio largamente utilizzato dalle librerie JavaScript.

    Apri una sandbox con i test.

    soluzione

    La soluzione sta nel ritornare loggetto stesso ad ogni chiamata.

    let ladder = {
      step: 0,
      up() {
        this.step++;
        return this;
      },
      down() {
        this.step--;
        return this;
      },
      showStep() {
        alert( this.step );
        return this;
      }
    };
    
    ladder.up().up().down().showStep().down().showStep(); // shows 1 then 0

    Possiamo anche scrivere una singola chiamata per riga. Per catene molto lunghe diventa pi leggibile:

    ladder
      .up()
      .up()
      .down()
      .showStep() // 1
      .down()
      .showStep(); // 0

    Apri la soluzione con i test in una sandbox.

    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