METODI STATICI

Possiamo anche assegnare metodi alle classi stesse, non solamente al loro “prototype”. Questi metodi sono detti statici. All’interno della JS classe, questi vengono preceduti dalla keyword static, come possiamo vedere nell’esempio:  

class User {

  static staticMethod() {

    alert(this === User);

  }

}

User.staticMethod(); // true

Il valore di this nella chiamata User.staticMethod() è rappresentato dal costruttore della classe User (la regola dell’oggetto prima del punto). Solitamente, i metodi statici vengono utilizzati per rappresentare funzioni che appartengono alla classe, ma non ad un oggetto in particolare. Ad esempio, potremmo avere degli oggetti di tipo Article e necessitare di una funzione per confrontarli. Una soluzione naturale sarebbe quella di aggiungere il metodo Article.compare, come nell’esempio:

class Article {

  constructor(titledate) {

    this.title title;

    this.date date;

  }

  static compare(articleAarticleB) {

    return articleA.date – articleB.date;

  }

}

// usage

let articles = [

  new Article(“HTML”new Date(2019, 1, 1)),

  new Article(“CSS”new Date(2019, 0, 1)),

  new Article(“JavaScript”new Date(2019, 11, 1))

];

articles.sort(Article.compare);

alertarticles[0].title ); // CSS

Qui Article.compare sta “al di sopra” degli articoli, poiché ha lo scopo di confrontarli. Non è un metodo di un articolo, ma piuttosto dell’intera classe. Un altro esempio comune è quello del “factory method” (un particolare design pattern). Immaginiamo di avere bisogno di diverse modalità di creazione di un articolo:

  1. Creazione con i parametri forniti (title, date etc).
  2. Creazione di un articolo vuoto con la data di oggi.
  3. …o qualsiasi altra modalità.

Il primo metodo può essere implementato tramite il costruttore. Mentre per il secondo, possiamo creare un metodo statico appartenente alla classe.

Come Article.createTodays() nell’esempio:

class Article {

  constructor(titledate) {

    this.title title;

    this.date date;

  }

  static createTodays() {

    // ricorda, this = Article

    return new this(“Today’s digest”new Date());

  }

}

let article Article.createTodays();

alertarticle.title ); // Today’s digest

Ora, ogni volta in cui avremo bisogno di creare un “today’s digest”, possiamo invocare Article.createTodays(). Ripetiamolo nuovamente, questo non è un metodo per uno specifico articolo, ma piuttosto un metodo dell’intera classe. I metodi di classe statici sono definiti sulla classe stessa. Non puoi chiamare un metodo statico su un oggetto, solo su una classe di oggetti.

class Car {
  constructor(name) {
    this.name name;
  }
  static hello() {
    return “Hello!!”;
  }
}
let myCar = new Car(“Ford”);
// You can call ‘hello()’ on the Car Class:
document.getElementById(“demo”).innerHTML = Car.hello();
// But NOT on a Car Object:
// document.getElementById(“demo”).innerHTML = myCar.hello();
// this will raise an error.

Se vuoi utilizzare l’oggetto myCar all’interno del metodo statico, puoi inviarlo come parametro:

class Car {
  constructor(name) {
    this.name name;
  }
  static hello(x) {
    return “Hello “ + x.name;
  }
}
let myCarnew Car(“Ford”);
document.getElementById(“demo”).innerHTML = Car.hello(myCar);

PROPRIETA’ STATICHE

È anche possibile definire proprietà statiche, queste sono molto simili alle proprietà della classe, ma sono precedute dalla keyword static:

class Article {

static publisher “Ilya Kantor”;

}

alertArticle.publisher ); // Ilya Kantor

EREDITARIETA’ DEI METODI E DELLE PROPRIETA’ STATICHE

Anche le proprietà ed i metodi statici vengono ereditati. Ad esempio, Animal.compare e Animal.planet nel codice sotto, vengono ereditate e diventano quindi accessibili come Rabbit.compare e Rabbit.planet:

class Animal {

static planet “Earth”;

constructor(namespeed) {

this.speed speed;

this.name name;

}

run(speed = 0) {

this.speed += speed;

alert(`${this.nameruns with speed ${this.speed}.`);

}

static compare(animalA, animalB) {

return animalA.speed – animalB.speed;

}

}

// Eredita da Animal

class Rabbit extends Animal {

hide() {

alert(`${this.namehides!`);

}

}

let rabbits = [

new Rabbit(“White Rabbit”, 10),

new Rabbit(“Black Rabbit”, 5)

];

rabbits.sort(Rabbit.compare);

rabbits[0].run(); // Black Rabbit runs with speed 5.

alert(Rabbit.planet); // Earth

Ora, quando invochiamo Rabbit.compare, verrà invocato il metodo Animal.compare ereditato.

Come funziona? Nuovamente, utilizzando il prototypes. Come potrete aver già intuito, extends fornisce a Rabbit il riferimento a [[Prototype]] di Animal.

Static Methods
  1. La funzione Rabbit eredita dalla funzione di Animal.
  2. prototype eredita il prototype di Animal.prototype.

Come risultato, l’ereditarietà funziona sia per i metodi regolari che per quelli statici.

Ora, verifichiamo quanto detto guardando al codice:

class Animal {}

class Rabbit extends Animal {}

// per proprietà statiche

alert(Rabbit.__proto__ === Animal); // true

// per proprietà regolari

alert(Rabbit.prototype.__proto__ === Animal.prototype); // true

Copy to Clipboard

IL LINGUAGGIO JAVASCRIPT

IL LINGUAGGIO JAVASCRIPT

LINK AL CODICE SU GITHUB

GITHUB