2016-01-19 7 views
12

Sto solo provando ES6 e voglio riscrivere una parte di codice scritta in javascript normale in ES6. E ora, sono bloccato mentre provo a riscrivere le proprietà e i metodi privati ​​nelle classi ES6. Sembra che le classi in ES6 non forniscano esplicitamente nulla per avere dati o metodi privati.Avere proprietà e metodi privati ​​nelle classi ES6

Inoltre, ho controllato questa discussione: Private properties in JavaScript ES6 classes e ho scoperto che era possibile utilizzare WeakMap per memorizzare dati privati. Il che è un po 'strano, ma può essere un problema. E sono riuscito a usarlo per dati privati.

Ma che dire dei metodi privati? Qual è il modo consigliato per avere metodi privati ​​ (o anche metodi protetti) nelle classi ES6?

Apprezzerei se qualcuno mi può mostrare un pulito modo di riscrivere questa parte di codice utilizzando la classe ES6 insieme ai metodi privati.

Grazie.

Ecco il codice javascript pianura vecchio:

function Deferred() { 

    // Private data 
    var isPending; 
    var handlers = { 
     resolve: [], 
     reject: [], 
     notify: [] 
    }; 

    // Initialize the instance 
    init(); 

    function init() { 
     isPending = true; 
     this.promise = new Promise(this); 
    } 

    // Public methods 
    this.resolve = function(value) { 
     trigger('resolve', value); 
    }; 

    this.reject = function(reason) { 
     trigger('reject', reason); 
    }; 

    this.notify = function(value) { 
     trigger('notify', value); 
    }; 

    this.on = function(event, handler) { 
     ... 
    }; 

    // Private method 
    function trigger (event, params) { 
     ... 
    } 
} 
+0

Ci dovrebbero essere informazioni sufficienti nell'articolo [* MDN: Classi *] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes). – RobG

risposta

12

Sembra che le classi in ES6 non prevede esplicitamente qualsiasi cosa per avere dati privati ​​o metodi.

Corretto. La sintassi class è per classi normali con metodi prototipo. Se si desidera variabili private, li metti nel costruttore di sempre:

class Deferred { 
    constructor() { 
     // initialise private data 
     var isPending = true; 
     var handlers = { 
      resolve: [], 
      reject: [], 
      notify: [] 
     }; 

     // Private method 
     function trigger(event, params) { 
      ... 
     } 

     // initialise public properties 
     this.promise = new Promise(this); 

     // and create privileged methods 
     this.resolve = trigger.bind(null, 'resolve'); 
     this.reject = trigger.bind(null, 'reject'); 
     this.notify = trigger.bind(null, 'notify'); 

     this.on = function(event, handler) { 
      … 
     }; 
    } 
} 
+3

Sembra essere a posto. Ma, se questo è l'unico modo, penso che sarebbe più "pulito" stare con il vecchio stile 'function()' di javascript. Poiché non c'è molto che potremmo fare in questo scenario con le classi ES6. – kabirbaidhya

+0

Beh, mi sarei aspettato che avessi almeno alcuni metodi di prototipazione, vero? – Bergi

+4

Il materiale "privato" qui è disponibile solo nel costruttore. Devi rinunciare all'utilizzo di getter di classe e setter e metodi di classe per far funzionare tutto (o almeno quelli che coinvolgono i membri apparentemente "privati"). In tal caso, sei ridotto a una funzione di generazione di un singolo oggetto, che non è affatto diversa dalle funzioni di classe "tradizionali". –

3

È possibile utilizzare simboli per dare una sorta-di membro privato.

const KEY = Symbol('key') 
const ANOTHER = Symbol('another') 

class Foo { 
    constructor() { 
    this[ KEY ] = 'private' 
    } 

    say() { 
    console.log(this[ KEY ]) 
    } 

    [ ANOTHER ] = 'transpilation required' 
} 

Il secondo simbolo è aggiunto alla classe utilizzando un class field, questo è solo nella proposta e richiederà transpilation di lavorare ovunque, ma il resto lavora a nodo e nuovi browser.

+0

questa è una sintassi strana, e si sente un po 'come un hack, ma funziona sicuramente ed è fondamentalmente equivalente ai membri privati ​​reali. –

+1

Anche se questa era una buona idea, ma la proprietà non è propriamente privata. Non è possibile accedere al valore con 'instance.key', ma è ancora possibile utilizzare l'istanza [Object.getOwnPropertySymbols (instance) .filter (s => s.toString(). Replace (/^Symbol \ (([^)] +) \) $ /, '$ 1') === 'chiave') [0]] ' – Neovov

+0

beh, potresti farlo ... – artparks