Skip to content

Latest commit

 

History

History
129 lines (97 loc) · 4.23 KB

File metadata and controls

129 lines (97 loc) · 4.23 KB

Costruttori

I costruttori in JavaScript sono differenti da quelli di molti altri linguaggi. Qualsiasi chiamata a funzione preceduta dalla parola chiave new agisce come un costruttore.

Dentro al costruttore (la funzione chiamata) il valore di this fa riferimento al nuovo oggetto creato. Il prototype di questo nuovo oggetto viene impostato al prototype dell'oggetto funzione che è stato invocato come costruttore.

Se la funzione che è stata chiamata non ha un'istruzione return esplicita, allora essa ritorna implicitamente il valore di this (il nuovo oggetto).

function Person(name) {
    this.name = name;
}

Person.prototype.logName = function() {
    console.log(this.name);
};

var sean = new Person();

Questo esempio chiama Person come costruttore ed imposta il prototype del nuovo oggetto creato a Person.prototype.

In caso di istruzione return esplicita, la funzione ritorna il valore specificato da quell'istruzione, ma solo se il valore di ritorno è un Object.

function Car() {
    return 'ford';
}
new Car(); // un nuovo oggetto, non 'ford'

function Person() {
    this.someValue = 2;

    return {
        name: 'Charles'
    };
}
new Person(); // l'oggetto ritornato ({name: 'Charles'}), escluso someValue

Quando la parola chiave new viene omessa, la funzione non ritornerà un nuovo oggetto.

function Pirate() {
    this.hasEyePatch = true; // imposta la proprietà nell'oggetto globale!
}
var somePirate = Pirate(); // somePirate è undefined

Mentre l'esempio precedente potrebbe sembrare essere funzionante in alcuni casi, a causa del modo in cui lavora this in JavaScript, esso userà l'oggetto globale come valore di this.

Factory (Fabbriche di oggetti)

Per poter omettere la parola chiave new, la funzione costruttore deve esplicitamente ritornare un valore.

function Robot() {
    var color = 'gray';
    return {
        getColor: function() {
            return color;
        }
    }
}
Robot.prototype = {
    someFunction: function() {}
};

new Robot();
Robot();

Entrambe le chiamate a Robot ritornano lo stesso risultato, un nuovo oggetto creato con una proprietà chiamata method, che è una Closure.

Bisogna anche notare che la chiamata new Robot() non influisce sul prototipo dell'oggetto ritornato. Mentre il prototipo sarà impostato con il nuovo oggetto creato, Robot non ritornerà mai quel nuovo oggetto.

Nell'esempio sopra, non c'è differenza funzionale nell'usare o meno la parola chiave new.

Creare nuovi oggetti tramite factory

Viene spesso raccomandato di non usare new perché una sua dimenticanza può portare a bug potenzialmente insidiosi da risolvere.

Per poter creare un nuovo oggetto, si dovrebbe invece usare una factory e costruire un nuovo oggetto all'interno di quella factory.

function CarFactory() {
    var car = {};
    car.owner = 'nobody';

    var milesPerGallon = 2;

    car.setOwner = function(newOwner) {
        this.owner = newOwner;
    }

    car.getMPG = function() {
        return milesPerGallon;
    }
    return car;
}

Sebbene questo esempio sia a prova di omissione della parola chiave new e renda sicuramente più semplice l'utilizzo delle variabili private, esso ha alcuni aspetti negativi.

  1. Usa più memoria dal momento che gli oggetti creati non condividono i metodi di un prototipo.
  2. Per poter ereditare, la factory deve copiare tutti i metodi da un altro oggetto oppure mettere quell'oggetto nel prototipo del nuovo oggetto.
  3. Perdere la catena di prototipi solo perché si vuole tralasciare la parola chiave new è contrario allo spirito del linguaggio.

In conclusione

Sebbene l'omissione della parola chiave new possa portare all'introduzione di bug, non è certo un motivo per privarsi completamente dell'uso dei prototipi. Alla fine si tratta di decidere quale sia la soluzione più adatta per l'applicazione. È specialmente importante scegliere uno specifico stile di creazione degli oggetti ed usarlo in maniera consistente.