Функция клас срещу фабрика: изследване на пътя напред

Discover Functional JavaScript бе обявен за една от най -добрите нови книги за функционално програмиране от BookAuthority !

ECMAScript 2015 (известен още като ES6) идва със classсинтаксиса, така че сега имаме два конкурентни модела за създаване на обекти. За да ги сравня, ще създам същата дефиниция на обект (TodoModel) като клас,и след това като фабрична функция.

TodoModel като клас

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

TodoModel като фабрична функция

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

Капсулиране

Първото нещо, което забелязваме, е, че всички членове, полета и методи на обект на клас са публични.

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

Липсата на капсулиране може да създаде проблеми със сигурността. Вземете примера за глобален обект, който може да бъде модифициран директно от Developer Console.

Когато се използва фабрична функция, само методите, които излагаме, са публични, а всичко останало е капсулирано.

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

това

thisПроблемите със загуба на контекст все още са налице при използване на клас. Например thisгуби контекст в вложени функции. Това е не само досадно по време на кодиране, но също така е постоянен източник на грешки.

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

или thisгуби контекст, когато методът се използва като обратно извикване, като при DOM събитие.

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

Няма такива проблеми при използване на фабрична функция, тъй като изобщо не се използва this.

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

тази и стрелката функция

Функцията стрелка частично решава проблемите с thisгубещия контекст в класове, но в същото време създава нов проблем:

  • this вече не губи контекст в вложени функции
  • this губи контекст, когато методът се използва като обратно повикване
  • стрелката функция насърчава използването на анонимни функции

Рефакторирах TodoModelизползването на стрелката. Важно е да се отбележи, че в процеса на рефакторинг на функцията стрелка можем да загубим нещо много важно за четливост, името на функцията. Вижте например:

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

Открийте функционалния JavaScript беше обявен за един отнай-добрите нови книги за функционално програмиране от BookAuthority !

За повече информация относно прилагането на техники за функционално програмиране в React разгледайте Functional React .

Научете функционален React , по проект, базиран на функционална архитектура с React и Redux .

Следвайте в Twitter