NodeJS (ES6): Pattern di progettazione con utilizzo di bind

3

La domanda è correlata alla risoluzione di questo operatore nelle classi Javascript. NodeJS ora supporta le classi ES6. Il problema affrontato durante questo è che quando una nuova istanza della classe viene creata e assegnata a una variabile, tutto funziona correttamente, ma se si assegna un particolare metodo di classe a una variabile, l'ambito della variabile viene perso.

class A {

    publicMethod() {
        console.log('Public Method');
        console.log('Calling Private Method');
        this._privateMethod();   
    }

    _privateMethod() {
        console.log('Private Method');
    }

}

class B extends A {
    constructor() {
        super();
        return  {
            publicMethod: this.publicMethod
        }
    }
}

class C extends A {
    constructor() {
        super();
        return  {
            publicMethod: this.publicMethod.bind(this)
        }
    }
}

La domanda è composta da due parti:

  1. Qual è l'effetto sulle prestazioni dell'uso del bind sui metodi di classe? Pensa che venga usato come una pratica in tutto l'ambito dell'applicazione. (quando si accede a publicMethod da B, genera un errore, ma non nel caso di A o C)
  2. È una buona pratica, al fine di supportare la visibilità, invece di non restituire nulla dal costruttore della classe, restituire alcuni metodi, che sono pensati per il pubblico, quindi abilitando la visibilità della classe. (Come in B e C)
posta Manish M Demblani 30.07.2018 - 15:32
fonte

1 risposta

1

Ritorno esplicito in Costruttore

Un ritorno esplicito in un costruttore restituisce un oggetto che non ha più il prototipo originale. Se lo hai gestito in modo che venga utilizzato il prototipo originale, allora è OK.

Tuttavia, è insolito e non posso davvero pensare a come questo potrebbe aiutarti. Perché, a quel punto, puoi semplicemente utilizzare una funzione regolare: la sintassi della classe ES6 non ti aiuta più.

Funzioni freccia

Penso che sarebbe meglio se lo facessi:

class B2 extends A {
    constructor() {
        super();
        this.publicMethod = () => super.publicMethod()
    }
}

Che è quasi identico all'utilizzo di bind, ma penso che sia più pulito usare le funzioni freccia.

Proprietà classe

In alternativa, babel ha il supporto per proprietà di classe che ti consente di scrivere codice che traspone semplicemente impostando un campo con una funzione di freccia (come B2) che assomiglia a questo:

class A {
    constructor() {
        this.i = 0
    }

    publicMethod = () => this.i++
}

Non utilizzare le funzioni di associazione / freccia

Potresti anche progettare la tua applicazione in modo da non dover utilizzare le funzioni di bind / freccia e avresti la situazione ideale in questo modo:

class B3 extends A {
    constructor() {
        super();
    }

    publicMethod() {
        super.publicMethod();
    }
}

A capo delle chiamate anziché dei metodi

Se non utilizzi le funzioni di bind / freccia, a volte dovrai comunque assicurarti che il contesto sia preservato.

A mio parere, è più coerente avvolgere semplicemente il contesto della chiamata al metodo all'interno di una funzione freccia o legare perché è il chiamante che determina il contesto in definitiva e dovrebbe essere il dovere del chiamante di occuparsene piuttosto che capire se l'autore ha impostato le cose correttamente per te. Puoi farlo in questo modo:

const a = new A();
const callback = () => a.method();
el.addEventListener('event', callback);

Puoi anche ottenere lo stesso effetto usando una funzione di ordine superiore che prende nel contesto per ottenere un effetto simile senza usare le funzioni di bind / freccia.

function wrapCall(a) {
    return function(event) { a.method(event) };
}

const a = new A();
const callback = wrapCall(a);
el.addEventListener('event', callback);

Prestazioni

L'uso del bind su una funzione non è particolarmente costoso. Ma risulta in più riferimenti alle funzioni poiché ogni istanza dell'oggetto ottiene una proprietà con la funzione in essa basata sull'originale. I metodi regolari ti consentono di condividere la funzione tra tutte le istanze poiché è memorizzata nel prototipo dell'oggetto.

Se devi creare nuove funzioni ogni volta che succede qualcosa, ad esempio, durante un rendering React, puoi creare molte funzioni inutilmente. Di solito è più economico utilizzare le funzioni di bind / freccia e archiviarlo semplicemente come un campo o da qualche parte accessibile. Tuttavia, se hai solo bisogno di creare un'istanza di una funzione per associarti a un DOM, è più economico utilizzare semplicemente una funzione freccia o associare quando aggiungi l'evento come nell'esempio precedente.

Sovraccarico di freccia e funzione limitata

Tecnicamente, una funzione freccia è più lenta di una funzione limitata e una funzione regolare è più veloce di entrambe. Tuttavia, questo è una sorta di una di quelle cose che non contano davvero nel mondo reale - il sovraccarico della chiamata di funzione probabilmente non produrrà o distruggerà il rendimento delle applicazioni. L'uso di memoria non necessaria creando ulteriori riferimenti è un problema più grande (anche se leggermente) e vale più tempo.

Conclusione

Sfortunatamente, nel mondo JS, le migliori pratiche sono piuttosto mal definite e ci sono molti modi per fare la stessa cosa; nessuno dei quali è chiaramente migliore di un altro. Probabilmente dovrai solo decidere in base alla situazione.

Esistono, tuttavia, alcune risorse che discutono l'argomento che mi sono imbattuto in individui più importanti che puoi dare un'occhiata. Sono focalizzati sulla reazione, ma credo che il principio si applichi ancora se leggi tra le righe.

risposta data 09.08.2018 - 22:58
fonte

Leggi altre domande sui tag