πŸ“œ ⬆️ ⬇️

Javascript: where we are and where to go

Hi, Habrayuzer. Since, apparently, we are already living in the future , I recently sat down to study new features of ES6, ES7 and new ideas proposed by React and Redux. And he wrote for his colleagues an article in which he outlined the sublimation of his own research. The article unexpectedly turned out to be quite voluminous, and I decided to publish it. I apologize in advance for some inconsistency in the presentation and reference to the proprietary code of our projects - but I think that it can still help some of us better understand where the JavaScript world is going, and why we should not ignore what is happening in it.


I’ll tell you about my thoughts on component models, classes, decorators, mixins, reactivity, pure functionality, immotable data structures, and the key idea of ​​React. I’ll say right away that I am not a React user, and all of this is the result of reading its documentation and technical articles explaining its architecture. That is, some idealized presentation, which is unconditionally only a simplified model of how everything is in reality.



So let's go. For the last couple of days I have been continuously learning the most modern JavaScript technologies in order to understand what is happening in the world, where to go, what to look at. The fact is that in the background I have been looking around for a long time, but so far I could not find time to study in depth the ideas proposed by React or ES7. Whereas, my experience showed that such ignoring of the surroundings goes sideways - in particular, I once spent a lot of time in my work for messing around with callbacks (probably, I should write about this in a separate article), simply because I had to study Promise - although I knew about this idea in general many years ago. And only when the last dog had already begun to use this concept - I understood how much time I wasted, ignoring this wonderful idea. And justifying it by the fact that I allegedly have no time to read about something there! This is very ironic. It is not enough just to be aware of something - sometimes you need to really sit down and study something thoroughly to understand it - and learn how to use it in your work.


I would not want this to happen again - especially when it comes to the implementation of a fairly serious project, on which the commercial success of a business depends. Time is money, and sometimes it is better to spend some time on research than one day to find yourself sitting in the middle of megatons of poorly working legacy code that is easier to rewrite than refactoring and debugging. It was with such a motivation that I started working on many abstractions from our framework several years ago, and this was justified then. And I am very pleased to find out now that all this time the world has been moving in exactly the same direction: everything that I have been working on in recent years, I discover in modern JS technologies that have become wildly popular during this time. Components, traits / mixins, type contracts, unit tests, declarativeness / functionality, etc etc ... Now 4 out of 5 new web projects are written to React - but a couple of years ago nobody knew about React. But all this automatically means that you need to look around and understand exactly how all these actively developing technologies are arranged in order not to step on a rake - and not to repeat what was done somewhere, perhaps better.


In general, I began to look at every single thing in our code and critically evaluate how well this is justified in the future, and how this is done by the β€œshop neighbors”. And in the course of this I found out a lot of interesting things - yes, such that for several days I can not sleep, trying to fix the chaos in my head from the information received.


Components


In our [comment: proprietary] framework, everything is tied to a system that simulates the semantics of classes using prototypes β€” and adds additional features to it:


ToggleButton = $component ({

    $depends: [DOMReference],

    $required: {
        label: 'string'
    },

    $defaults: {
        color: 'red'
    },

    onclick: $trigger (),

    toggled: $observable (false),
    checked: $alias ('toggled'), // 

    coolMethod: $static ($debounce ($bindable ($memoize (function () { ... })))),

})

β€” $static, $trigger, $observable , «» . , . $trigger , .


, . , β€” . ES7 ( ), , β€” , - . , , , .


$depends traits (), . , . , $defaults , - . , recalcLayout β€” , afterRecalcLayout. observables. Traits traits. β€” require . , .


this β€” - :


button.touched (this.doLogout)

ES6


, JavaScript β€” , . . JS , ! , JavaScript - . β€”  β€” - , . - . ES6 .


ES6 , (JSON), β€” -, -, , . , $memoize, . $depends β€” ES6 , $depends: [...], .


, ES6. , JavaScript - , class new ! , :



TL/DR: , , Object.create. , : new , β€” «», .


, , ES6 β€” β€” (embedded DSL) , .


ES7


JS, , . , , , β€” :


Button = @component class {

    @trigger onclick () {}
    @observable toggled = false

    @debounce @bindable @memoize static coolMethod () {}
}

, (), . , .


. , , β€” Chai Spies. , ES6/ES7, (Proxy Objects, Symbols).


, $required $depends - , . , JavaScript , :


class Button {

    depends: [DOMReference]

    @required label: 'string'
    @required color: 'red'

, class public fields, - :


class Button {

    depends = [DOMReference]

    @required label = 'string'
    @required color = 'red'

- ( proposal ) , ( ) , , β€” , - … , .


, . , @required label: 'string' . , ? , , , β€” ...


Babel...


… , JavaScript-, . , Babel β€” , . !


 β€” JavaScript, ES6/ES7/ES.Next JS, β€” . , . , public class fields β€” . Babel β€” . .


Babel, ES5  β€” IE. , .


Babel , , , - , . , . source maps β€” , , β€” .


React


, React. Facebook β€” , . , , : , , ...


Button = React.createClass ({

  mixins: [SomeMixin]

  propTypes: {
    label: React.PropTypes.string.isRequired
  },

  render () { ... }
})

, React β€” - - . , React β€” . , 90% , «» β€” , Babel. .


, React ! , , , β€” , . React , , , , . , - β€” . β€” , β€” React, , . , , «» , FRP… , β€” , . , , β€” , . β€” .



, «» - :


ToggleButton = ({ label, toggled }) => <button toggled="{toggled}">{label}</button>

ToggleButton ({ label: '?', toggled: true }) // <button toggled="true">?</button>

, β€” , DOM. . β€” . - , WTF? , JavaScript c ?


«» ToggleButton ():


ToggleButton = $component ({

    $required: { label: 'string' },
    $defaults: { toggled: false },

    render () { return <button checked="{this.toggled}">{this.label}</button> }
})

new ToggleButton ({ label: ' , -?', toggled: false }).render ()

, . , ? ! ( new), β€” . β€” ES6 - .


β€” . . ? -, ES6 , destructuring-:


ToggleButton ({ label, toggled = false }) => ...

-, : Flow vs TypeScript. . , JavaScript. . Flow ( ) JavaScript β€” ToggleButton :


ToggleButton = ({ label : String, toggled = false }) => <button toggled="{toggled}">{label}</button>

label ! «» β€” , run-time. , run-time β€” :


ToggleButton ({ toggled: false }) //   label

, «» β€” , , β€” , map reduce...


, , - console.log β€” , , . β€” , ! , β€” , . , . DOM, .


, β€” , . «» DOM- β€” , , . , , UI- β€” DOM . , - JSON-, , , toggled , DOM β€” setAttribute ('toggled', toggled) . , β€” , React, : «» , - console.log:


ToggleButton = ({ label, toggled }) => <button toggled="{toggled}">{label}</button>

, React . , (ad-hoc) … , ! React , . Β« Β»:  Β« -Β» β€” , - β€” React . , . . , Β« Β» , . , - β€” , β€” .


, , ?


channels Β« Β» β€” Β« Β». , Promise β€” . , label toggled , Β« Β», . DOM , . , setAttribute ('toggled', toggled) , , . , . map, filter, reduce β€” … Β« Β» «», async/await . , β€” . , Β« Β» β€” - . Β« Β».


React? , ! - , observables, , ( ) β€” , .


React, :


  1. β€” ,
  2. , - observable- β€” , «»

, , :


data = { todos: [ { toggled: true, label: '' }, { toggled: false, label: ' ' } ] }

DOM-:


TodoList = ({ todos }) =>
    <h1></h1>
    <content>{ todos.map (ToggleButton) }</content>

:


render (TodoList (data)) // - console.log

, «» render. ToggleButton TodoList DOM β€” . - toggled, ToggleButton β€” . DOM, ? React "blueprint" ( React Virtual DOM) β€” DOM, β€” . - :


{ type: 'button', props: { toggled: true, children: [''] } }

, render , DOM β€” . , , , diff. DOM. , ...


{ type: 'button', props: { toggled: true, children: [''] } }

{ type: 'button', props: { toggled: false, children: [''] } }

… setAttribute ('toggled', false) DOM . , JavaScript- , DOM . β€” , DOM.


React : . . ?


React - , :


  1. Β« Β» , Β« Β». . DOM, VDOM, - β€” , VDOM ?


  2. VDOM β€” VDOM, , - . ?

React, .


-, diff β€” . ? 10000 , .


VDOM β€” , . - (TodoList, ToggleButton) VDOM- β€” VDOM, β€” . . , - VDOM, «» , β€” , . , β€” . , , β€” . ! β€” ( ). ( ) . ! β€” ...


ToggleButton? , , , ? VDOM, ? . , , VDOM? β€” ! ...



VDOM, - β€” , . , todos[1].toggled = true β€” . , , TodoList , todos β€” β€” . «» , . , VDOM ! , - «» β€” , .


β€” β€” , … , , [1].toggled = true, - :


todos = todos.set (1, Object.assign ({}, todos[1], { toggled: true }))

.set β€” , , 1 β€” , . , DOM β€” .


, ( ) Β« Β» , β€” Β« , , Β».


, , Immutable.js. , JavaScript β€” Object.freeze β€” , , .


, Proxy Objects, JavaScript, , :


todos = todos[1].toggled.set (true) //   todos

«» !


Redux


, , Redux - . , undo/redo β€” , β€” β€” , React.


, React , β€” , Redux. , :


  1. β€” (previous state β†’ new state)
  2. (-)

, - :


addTodo (oldState, label) => ({ todos: oldState.todos.concat ({ label: label, checked: false }) })
checkTodo (oldState, index) => ({ todos: ...

( , ), Redux:


reduce (oldState, action) => {
    switch (action.type) {
        case ADD_TODO: return { todos: oldState.todos.concat ({ label: action.label, checked: false }
        case CHECK_TODO: return { ...

, … .



, - β€” . , «» React β€” , β€” React , . - , - - DOM . , Β« Β» . React Fiber Architecture, , - - , , . , Prerequisites β€” .


')

Source: https://habr.com/ru/post/308154/


All Articles