Klasse vs fabriksfunktion: udforske vejen frem

Discover Functional JavaScript blev udnævnt til en af ​​de bedste nye funktionelle programmeringsbøger af BookAuthority !

ECMAScript 2015 (aka ES6) kommer med classsyntaksen, så nu har vi to konkurrerende mønstre til at skabe objekter. For at sammenligne dem opretter jeg den samme objektdefinition (TodoModel) som en klasse,og derefter som en fabriksfunktion.

TodoModel som en klasse

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

TodoModel som en fabriksfunktion

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

Indkapsling

Det første vi bemærker er, at alle medlemmer, felter og metoder til et klasseobjekt er offentlige.

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

Manglen på indkapsling kan skabe sikkerhedsproblemer. Tag eksemplet på et globalt objekt, der kan ændres direkte fra Developer Console.

Når du bruger fabriksfunktion, er kun de metoder, vi udsætter, offentlige, alt andet er indkapslet.

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

dette

thisat miste kontekstproblemer er der stadig, når du bruger klasse. For eksempel thiser at miste sammenhæng i indlejrede funktioner. Det er ikke kun irriterende under kodning, men det er også en konstant kilde til fejl.

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

eller thismister kontekst, når metoden bruges som tilbagekald, som ved en DOM-begivenhed.

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

Der er ingen sådanne problemer, når du bruger en fabriksfunktion, da den slet ikke bruger this.

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

dette og pil funktion

Pile-funktionen løser delvist de thisløsende kontekstproblemer i klasser, men skaber samtidig et nyt problem:

  • this mister ikke længere sammenhæng i indlejrede funktioner
  • this mister kontekst, når metoden bruges som tilbagekald
  • pilfunktion fremmer brugen af ​​anonyme funktioner

Jeg refactored TodoModelbrug af pilen funktion. Det er vigtigt at bemærke, at vi i processen med refactoring til pilfunktionen kan miste noget meget vigtigt for læsbarheden, funktionsnavnet. Se for eksempel på:

//using function name to express intent setTimeout(function renderTodosForReview() { /* code */ }, 0); //versus using an anonymous function setTimeout(() => { /* code */ }, 0);

Discover Functional JavaScript blev udnævnt til et afbedste nye funktionelle programmeringsbøger fra BookAuthority !

For mere om anvendelse af funktionelle programmeringsteknikker i React, se på Functional React .

Lær funktionel reaktion på en projektbaseret måde med funktionel arkitektur med React og Redux .

Følg på Twitter