Skip to content

Static properties and methods #231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
First, let's see why the latter code doesn't work.
Come prima cosa, cerchiamo di capire perché il codice non funziona.

The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. Otherwise `"this"` won't be "defined".
La motivazione appare piuttosto ovvia se proviamo ad eseguire il codice. Un classe che eredita, deve invocare `super()`. Diversamente, il valore di `"this"` non sarà "definito".

So here's the fix:
Vediamo come sistemarlo:

```js run
class Rabbit extends Object {
constructor(name) {
*!*
super(); // need to call the parent constructor when inheriting
super(); // dobbiamo chiamare il costruttore padre della classe da cui stiamo ereditando
*/!*
this.name = name;
}
Expand All @@ -19,16 +19,16 @@ let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // true
```

But that's not all yet.
Ma non è tutto.

Even after the fix, there's still important difference in `"class Rabbit extends Object"` versus `class Rabbit`.
Anche dopo questo fix, c'è ancora un grande differenza tra `"class Rabbit extends Object"` e `class Rabbit`.

As we know, the "extends" syntax sets up two prototypes:
Come già sappiamo, la sintassi "extends" imposta due prototype:

1. Between `"prototype"` of the constructor functions (for methods).
2. Between the constructor functions themselves (for static methods).
1. Tra `"prototype"` del costruttore (per i metodi).
2. Tra i costruttori stessi (per i metodi statici).

In our case, for `class Rabbit extends Object` it means:
Nel nostro caso, `class Rabbit extends Object` significa:

```js run
class Rabbit extends Object {}
Expand All @@ -37,45 +37,45 @@ alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) true
```

So `Rabbit` now provides access to static methods of `Object` via `Rabbit`, like this:
In questo modo, tramite `Rabbit` abbiamo accesso ai metodi statici di `Object`, come nell'esempio:

```js run
class Rabbit extends Object {}

*!*
// normally we call Object.getOwnPropertyNames
// normalmente invochiamo Object.getOwnPropertyNames
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
*/!*
```

But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`.
Ma se non estendiamo l'oggetto, con`extends Object`, allora `Rabbit.__proto__` non sarà impostato a `Object`.

Here's the demo:
Qui una demo:

```js run
class Rabbit {}

alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) false (!)
alert( Rabbit.__proto__ === Function.prototype ); // as any function by default
alert( Rabbit.__proto__ === Function.prototype ); // come qualsiasi funzione di default

*!*
// error, no such function in Rabbit
// errore, funzione non esistente in Rabbit
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
*/!*
```

So `Rabbit` doesn't provide access to static methods of `Object` in that case.
Quindi `Rabbit`, in questo caso, non fornisce l'accesso ai metodi statici di `Object`.

By the way, `Function.prototype` has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`.
In ogni caso, `Function.prototype` possiede metodi "generici", come `call`, `bind` etc. Questi saranno disponibili in entrambi i casi, grazie al costruttore di `Object`, `Object.__proto__ === Function.prototype`.

Here's the picture:
Come mostrato in figura:

![](rabbit-extends-object.svg)

So, to put it short, there are two differences:
Quindi, per riassumere, ci sono due principali differenze:

| class Rabbit | class Rabbit extends Object |
|--------------|------------------------------|
| -- | needs to call `super()` in constructor |
| -- | dobbiamo invocare `super()` nel costruttore |
| `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` |
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ importance: 3

# Class extends Object?

As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods like `hasOwnProperty` etc.
Come ormai sappiamo, tutti gli oggetti, normalmente ereditano da `Object.prototype` ed hanno accesso ai metodi generici di `Object`, come `hasOwnProperty` etc.

For instance:
Ad esempio:

```js run
class Rabbit {
Expand All @@ -18,16 +18,16 @@ class Rabbit {
let rabbit = new Rabbit("Rab");

*!*
// hasOwnProperty method is from Object.prototype
// hasOwnProperty viene ereditato da Object.prototype
alert( rabbit.hasOwnProperty('name') ); // true
*/!*
```

But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`?
Ma se lo invocassimo esplicitamente in questo modo: `"class Rabbit extends Object"`, allora il risultato sarebbe diverso da un semplice `"class Rabbit"`?

What's the difference?
Qual'è la differenza?

Here's an example of such code (it doesn't work -- why? fix it?):
Qui vediamo un esempio (perché non funziona? è possibile sistemarlo?):

```js
class Rabbit extends Object {
Expand Down
86 changes: 43 additions & 43 deletions 1-js/09-classes/03-static-properties-methods/article.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

# Static properties and methods
# Proprietà e metodi statici

We can also assign a method to the class function itself, not to its `"prototype"`. Such methods are called *static*.
Possiamo anche assegnare metodi alle classi stesse, non solamente al loro `"prototype"`. Questi metodi sono detti *statici*.

In a class, they are prepended by `static` keyword, like this:
All'interno della classe, questi vengono preceduti dalla keyword `static`, come possiamo vedere nell'esempio:

```js run
class User {
Expand All @@ -17,7 +17,7 @@ class User {
User.staticMethod(); // true
```

That actually does the same as assigning it as a property directly:
Questo avrà lo stesso effetto di assegnarla direttamente come proprietà:

```js run
class User { }
Expand All @@ -29,11 +29,11 @@ User.staticMethod = function() {
User.staticMethod(); // true
```

The value of `this` in `User.staticMethod()` call is the class constructor `User` itself (the "object before dot" rule).
Il valore di `this` nella chiamata `User.staticMethod()` è rappresentato dal costruttore dell classe `User` (la regola dell' "oggetto prima del punto").

Usually, static methods are used to implement functions that belong to the class, but not to any particular object of it.
Solitamente, i metodi statici vengono utilizzati per rappresentare funzioni che appartengono alla classe, ma non ad un oggetto in particolare.

For instance, we have `Article` objects and need a function to compare them. A natural solution would be to add `Article.compare` method, like this:
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:

```js run
class Article {
Expand Down Expand Up @@ -63,17 +63,17 @@ articles.sort(Article.compare);
alert( articles[0].title ); // CSS
```

Here `Article.compare` stands "above" articles, as a means to compare them. It's not a method of an article, but rather of the whole class.
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.

Another example would be a so-called "factory" method. Imagine, we need few ways to create an article:
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. Create by given parameters (`title`, `date` etc).
2. Create an empty article with today's date.
3. ...or else somehow.
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à.

The first way can be implemented by the constructor. And for the second one we can make a static method of the class.
Il primo metodo può essere implementato tramite il costruttore. Mentre per il secondo, possiamo creare un metodo statico appartenente alla classe.

Like `Article.createTodays()` here:
Come `Article.createTodays()` nell'esempio:

```js run
class Article {
Expand All @@ -84,7 +84,7 @@ class Article {

*!*
static createTodays() {
// remember, this = Article
// ricorda, this = Article
return new this("Today's digest", new Date());
}
*/!*
Expand All @@ -95,21 +95,21 @@ let article = Article.createTodays();
alert( article.title ); // Today's digest
```

Now every time we need to create a today's digest, we can call `Article.createTodays()`. Once again, that's not a method of an article, but a method of the whole class.
Ora, ogni volta in cui avremo bisogno di crare 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.

Static methods are also used in database-related classes to search/save/remove entries from the database, like this:
I metodi statici vengono utilizzati anche nelle classi database-related (relative a database), per poter cercare/salvare/rimuovere elementi dal database, come nell'esempio:

```js
// assuming Article is a special class for managing articles
// static method to remove the article:
// assumiamo che Article sia una classe speciale per la gestione degli articoli
// metodo statico per la rimozione di un articolo:
Article.remove({id: 12345});
```

## Static properties
## Proprietà statiche

[recent browser=Chrome]

Static properties are also possible, they look like regular class properties, but prepended by `static`:
E' anche possibile definire proprietà statiche, queste sono molto simili alle proprietà della classe, ma sono precedute dalla keyword `static`:

```js run
class Article {
Expand All @@ -119,17 +119,17 @@ class Article {
alert( Article.publisher ); // Ilya Kantor
```

That is the same as a direct assignment to `Article`:
Lo stesso che si otterrebbe con un assegnazione diretta ad `Article`:

```js
Article.publisher = "Ilya Kantor";
```

## Inheritance of static properties and methods
## Ereditarietà delle proprietà e dei metodi statici

Static properties and methods are inherited.
Anche le proprietà ed i metodi statici vengono ereditati.

For instance, `Animal.compare` and `Animal.planet` in the code below are inherited and accessible as `Rabbit.compare` and `Rabbit.planet`:
Ad esempio, `Animal.compare` e `Animal.planet` nel codice sotto, vengono ereditate e diventano quindi accessibili come `Rabbit.compare` e `Rabbit.planet`:

```js run
class Animal {
Expand All @@ -153,7 +153,7 @@ class Animal {

}

// Inherit from Animal
// Eredita da Animal
class Rabbit extends Animal {
hide() {
alert(`${this.name} hides!`);
Expand All @@ -174,43 +174,43 @@ rabbits[0].run(); // Black Rabbit runs with speed 5.
alert(Rabbit.planet); // Earth
```

Now when we call `Rabbit.compare`, the inherited `Animal.compare` will be called.
Ora, quando invochiamo `Rabbit.compare`, verrà invocato il metodo `Animal.compare` ereditato.

How does it work? Again, using prototypes. As you might have already guessed, `extends` gives `Rabbit` the `[[Prototype]]` reference to `Animal`.
Come funziona? Nuovamente, utilizzando il prototypes. Come potrete aver già intuito, `extends` fornisce a `Rabbit` il riferimento a `[[Prototype]]` di `Animal`.

![](animal-rabbit-static.svg)

![](animal-rabbit-static.svg)

1. `Rabbit` function prototypally inherits from `Animal` function.
2. `Rabbit.prototype` prototypally inherits from `Animal.prototype`.
1. La funzione `Rabbit` eredita dalla funzione di `Animal` .
2. `Rabbit.prototype` eredita il prototye di `Animal.prototype`.

As a result, inheritance works both for regular and static methods.
Come risultato, l'ereditarietà funziona sia per i metodi regolari che per quelli statici.

Here, let's check that by code:
Ora, verifichiamo quanto detto guardando al codice:

```js run
class Animal {}
class Rabbit extends Animal {}

// for statics
// per proprietà statiche
alert(Rabbit.__proto__ === Animal); // true

// for regular methods
// per proprietà regolari
alert(Rabbit.prototype.__proto__ === Animal.prototype); // true
```

## Summary
## Riepilogo

Static methods are used for the functionality that belongs to the class "as a whole". It doesn't relate to a concrete class instance.
I metodi statici vengono utilizzati per funzionalità che appartengono all'intera classe. Non hanno nulla a che fare con l'istanza della classe.

For example, a method for comparison `Article.compare(article1, article2)` or a factory method `Article.createTodays()`.
Ad esempio, un metodo per il confronto `Article.compare(article1, article2)` o un factory method `Article.createTodays()`.

They are labeled by the word `static` in class declaration.
Queste vengono precedute dalla keyword `static` all'interno della dichiarazione della classe.

Static properties are used when we'd like to store class-level data, also not bound to an instance.
Le proprietà statiche vengono utilizzate quando si ha intenzione di memorizzare dati relativi alla classe, che non sono quindi legati ad un'istanza precisa.

The syntax is:
La sintassi è:

```js
class MyClass {
Expand All @@ -222,13 +222,13 @@ class MyClass {
}
```

Technically, static declaration is the same as assigning to the class itself:
Tecnicamente, le dichiarazioni di proprietà statiche equivalgono all'assegnazione diretta alla classe stessa:

```js
MyClass.property = ...
MyClass.method = ...
```

Static properties and methods are inherited.
Le proprietà ed i metodi statici vengono ereditati.

For `class B extends A` the prototype of the class `B` itself points to `A`: `B.[[Prototype]] = A`. So if a field is not found in `B`, the search continues in `A`.
Nel caso in cui `class B extends A` il prototype della classe `B` punta ad `A`: `B.[[Prototype]] = A`. Quindi se un campo non viene trovato in `B`, la ricerca continuerà in `A`.