Descoperiți JavaScript funcțional a fost numit unul dintre cele mai bune cărți noi de programare funcțională de BookAuthority!

ECMAScript 2015 (alias ES6) vine cu class sintaxă, așa că acum avem două modele concurente pentru crearea obiectelor. Pentru a le compara, voi crea aceeași definiție a obiectului (TodoModel) ca o clasă, și apoi ca funcție din fabrică.

TodoModel ca clasă

class TodoModel {
    constructor(){
        this.todos = [];
        this.lastChange = null;
    }
    
    addToPrivateList(){
        console.log("addToPrivateList"); 
    }
    add() { console.log("add"); }
    reload(){}
}

TodoModel ca funcție din fabrică

function TodoModel(){
    var todos = [];
    var lastChange = null;
        
    function addToPrivateList(){
        console.log("addToPrivateList"); 
    }
    function add() { console.log("add"); }
    function reload(){}
    
    return Object.freeze({
        add,
        reload
    });
}

Incapsularea

Primul lucru pe care îl observăm este că toți membrii, câmpurile și metodele unui obiect de clasă sunt publice.

var todoModel = new TodoModel();
console.log(todoModel.todos);     //[]
console.log(todoModel.lastChange) //null
todoModel.addToPrivateList();     //addToPrivateList

Lipsa încapsulării poate crea probleme de securitate. Luați exemplul unui obiect global care poate fi modificat direct din Consola pentru dezvoltatori.

ad-banner

Atunci când se utilizează funcția din fabrică, numai metodele pe care le expunem sunt publice, orice altceva este încapsulat.

var todoModel = TodoModel();
console.log(todoModel.todos);     //undefined
console.log(todoModel.lastChange) //undefined
todoModel.addToPrivateList();     //taskModel.addToPrivateList
                                    is not a function

acest

this pierderea problemelor de context sunt încă acolo atunci când se utilizează clasa. De exemplu, this pierde contextul în funcțiile imbricate. Nu este doar enervant în timpul codării, ci este și o sursă constantă de bug-uri.

class TodoModel {
    constructor(){
        this.todos = [];
    }
    
    reload(){ 
        setTimeout(function log() { 
           console.log(this.todos);    //undefined
        }, 0);
    }
}
todoModel.reload();                   //undefined

sau this pierde contextul când metoda este utilizată ca apel invers, ca la un eveniment DOM.

$("#btn").click(todoModel.reload);    //undefined

Nu există astfel de probleme atunci când se utilizează o funcție din fabrică, deoarece nu o folosește this deloc.

function TodoModel(){
    var todos = [];
        
    function reload(){ 
        setTimeout(function log() { 
           console.log(todos);        //[]
       }, 0);
    }
}
todoModel.reload();                   //[]
$("#btn").click(todoModel.reload);    //[]

aceasta și funcția săgeată

Funcția săgeată rezolvă parțial this pierderea problemelor de context în clase, dar în același timp creează o nouă problemă:

  • this nu mai pierde contextul în funcțiile imbricate
  • this pierde contextul când metoda este utilizată ca apel invers
  • funcția săgeată promovează utilizarea funcțiilor anonime

Am refactorizat TodoModel folosind funcția săgeată. Este important să rețineți că în procesul de refactorizare a funcției săgeată putem pierde ceva foarte important pentru lizibilitate, numele funcției. Uită-te de exemplu la:

//using function name to express intent
setTimeout(function renderTodosForReview() { 
      /* code */ 
}, 0);

//versus using an anonymous function
setTimeout(() => { 
      /* code */ 
}, 0);

Descoperiți JavaScript funcțional a fost numit unul dintre cele mai bune cărți noi de programare funcțională de BookAuthority!

Pentru mai multe despre aplicarea tehnicilor funcționale de programare în React, aruncați o privire Reactie functionala.

Învăța funcțional React, într-un mod bazat pe proiecte, cu Arhitectură funcțională cu React și Redux.

Urmăriți pe Twitter