📜 ⬆️ ⬇️

Overview of the features of modern JavaScript

JavaScript is probably the most well-known multi-paradigm language, with a lot of non-obvious features. Nevertheless, whether we love it or scold it, the fact remains that it is the main language on which the modern web works.

Last year, the standard ECMAScript 2015 (informally ES6) was released, which greatly changed what we are used to. There is a mass of new features, which in essence are a modern superset of the language trying to solve existing problems. Class, let, const, switch functions ... the developer, who had not previously seen the code written in ES6, did not immediately realize that he was, in fact, good old JS.

There are lots of wonderful articles on modern standards. In the same post, I want to show what modern JS can offer us when it is necessary to solve an urgent problem. For example, to congratulate everyone on the New Year.

Imperative approach


The easiest decision to do is imperative. Yes, indeed, if you follow the principle “less is more - more is less”, then this will be the most pragmatic solution:
')
function sayHappyNewYear(year){ console.log('Happy New ' + year + ' Year!'); } sayHappyNewYear(2016); 


The solution is simple, and it will work in all environments where there is an implementation of the console object, but there is a flaw in it: we have not only the New Year, but many other holidays. Creating a separate function for each holiday is not a very sensible task. If we need to format the messages uniformly, then when the message format is changed, it will be necessary to change the corresponding code in all functions (yes, the examples in the article turned out to be a bit artificial). You can, of course, take everything connected with formatting into a separate function formatMessage () and pass through it a greeting in all functions. But let's first try to reflect the subject area using OOP and see how JavaScript can help us in this situation.

Object oriented approach


As you all know well in JS, you can write in object-oriented style with prototype-based inheritance:

 function Greeter() {} Greeter.prototype.doGreeting = function(msg) { console.log(msg); } function NewYearGreeter(currentYear) { this.currentYear = currentYear; } NewYearGreeter.prototype = Object.create(Greeter.prototype); NewYearGreeter.prototype.constructor = NewYearGreeter; NewYearGreeter.prototype.doGreeting = function() { var year = this.currentYear + 1; var newYearMsg = 'Happy New ' + year + ' Year!'; Greeter.prototype.doGreeting.call(this, newYearMsg); } var newYearGreeter = new NewYearGreeter(2015); newYearGreeter.doGreeting(); 


It turned out quite a verbose solution, plus of which is that this code will work in all modern runtime environments (browsers, Node.js). It is because of the verbosity of the implementation of the object-oriented approach that classes appeared in ES6 that are familiar to any programmer who owns C ++, Java, C #, Python, etc. This is how the example above will look like if you use the ES6 classes:

 'use strict'; class Greeter { doGreeting(msg) { console.log(msg); } } class NewYearGreeter extends Greeter { constructor(currentYear) { super(); this.currentYear = currentYear; } doGreeting() { let year = this.currentYear + 1; let newYearMsg = 'Happy New ' + year + ' Year!'; super.doGreeting(newYearMsg); } } let newYearGreeter = new NewYearGreeter(2015); newYearGreeter.doGreeting(); 


Looks already prettier. But as you probably know there was a lot of controversy around classes in JS. There were ardent opponents of this innovation. On the whole, their position was clear - in the future, the PLO raises the problem of a “gorilla and a banana”:

The problem with object-oriented languages ​​is that they carry with them all their implicit surroundings. You needed a banana - and you get a gorilla with a banana, and the whole jungle in addition.
Joe Armstrong "Coders at Work"

Therefore, the linguistic means that made it possible to create a complex taxonomy of classes in a simple way were perceived by the opposing side with bayonets. However, classes are now the standard of the language, use, but without fanaticism.

Well, if inheritance creates a connectivity problem, what is the alternative? Composition.

Prefer object composition to class inheritance
Gamma, Helm, Johnson, Vlissides “Object-oriented design techniques. Design patterns. "

In JS, the composition can be implemented in different ways. Here is one of the solutions that will work in all modern runtime environments:

 function extend(destination, source) { for (var key in source) { if (source.hasOwnProperty(key)) { destination[key] = source[key]; } } } function Greeter() { this.doGreeting = function(msg) { console.log(msg); } } function NewYearGreeter(year) { this.year = year; this.doNewYearGreeting = function() { var newYearMsg = 'Happy New ' + this.year + ' Year!'; this.doGreeting(newYearMsg); } } var greeter = new Greeter; var newYearGreeter = new NewYearGreeter(2016); extend(newYearGreeter, greeter); newYearGreeter.doNewYearGreeting(); 


In this example, using constructors, objects are created whose properties (methods) are arranged in one entity (object newYearGreeter) using the extend service function. The modern standard allows to simplify the implementation of the composition using Object.assign ():

 'use strict'; let greeter = { doGreeting(msg) { console.log(msg); } }; let newYearGreeter = { setYear(year) { this.year = year; }, doNewYearGreeting() { let newYearMsg = 'Happy New ' + this.year + ' Year!'; this.doGreeting(newYearMsg); } }; Object.assign(newYearGreeter, greeter); newYearGreeter.setYear(2016); newYearGreeter.doNewYearGreeting(); 


Object.assign () essentially does the same thing as extend, with the exception that you can use it out of the box while you can assemble any number of objects.

This is the object side of the question. But JS also provides tools for programming in a functional style.

Functional style


The peculiarity of this approach is that we no longer operate with objects, but operate with pure functions , the composition of which allows us to solve the problem posed. Our example is too small, so for example let's take another concept from functional programming - currying :

 function createGreeter(msg) { return function(param) { return msg.replace(/%.*%/, param); } } var greetWithNewYear = createGreeter('Happy New %year% Year!'); console.log(greetWithNewYear(2016)); 


In ES6, from the means to simplify programming in a functional style, the most notable innovation is the switch functions. The arrow function is an anonymous function (for example, a function immediately after the return from the example above) or a lambda expression, as the people from the functional camp say. This is how our example is converted if we use the “fat arrow”:

 function createGreeter(msg) { return param => msg.replace(/%.*%/, param); } var greetWithNewYear = createGreeter('Happy New %year% Year!'); console.log(greetWithNewYear(2016)); 


Programming in a functional style offers many advantages: the code is more compact without side effects, but, of course, you need to get used to it, because with functional programming, reasoning moves from the imperative level to the declarative level (what to do).

What to read / see?


Axel Rauschmayer's blog:

The ES6 in Depth series on mozilla.org:

Matthias Johnson Youtube Channel :


Results


JavaScript is developing very quickly - the future standard is preparing other great innovations in the language, but what we can use to create web applications today is by and large a new incarnation of the language, the purpose of which is to simplify the lives of all developers.

 (_ => ++_)(2015); 

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


All Articles