S.Tominoff

Fullstack JavaScript разработчик

Modern JavaScript: ТОП-3 синтаксических конструкций современного JS

Самые крутые синтаксические конструкции JavaScript по версии месье Томинова и авторский обзор.

JavaScript развивается стремительными темпами, в язык постоянно добавляются новые возможности. Кажется, ещё вчера JS считали жалкой игрушкой верстальщиков для наворачивания простых скриптов в вёрстке.

 

Пожалуй, так оно и было — язык с кучей проблем совместимости браузеров, "непонятным" ООП на прототипах, всплытием переменных и странным this. Самая крутая библиотека — jQuery, а самое крутое приложение — почтовый веб клиент от Гугл.

 

 

Однако, времена меняются и сегодня JavaScript используется как для построения сложных web–интерфейсов, так и во многих других сферах, начиная с утилит автоматизации и до серверного node.js.

 

Предлагаю к рассмотрению 3 самые удачные, по мнению автора, синтаксические конструкции в современном JS.

 

№1 Стрелочные лямбда функции 

() => {}, () => ()

 

Лямбды, или анонимные функции появились сравнительно давно, однако это та часть синтаксиса, которая лично меня повергла в настоящий восторг, когда я впервые о ней узнал 🔥

 

Изначально, пришли они к нам из CoffeeScript (помните такой? 😉), где именовались не иначе как fat-arrow-functions

Основная фича таких функций — отсутствие собственного контекста

 

// arrow-function: самая обычная функция:
square = num -> num * num // -> function square (num) { return num * num }

// fat-arrow-function: функция с замыканием контекста:
Something = () ->
  @fired = false // то же что this.fired = false
  setTimeout () =>
    @fired = true
  , 1000

// получаем что-то вроде
function Something () {
  this.fired = false
  // замыкаем контекст с помощью IIFE
  setTimeout((function (_this) {
    _this.fired = true
  })(this), 1000)
}

 

Конечно, во времена первых версий CoffeeScript, контекст у таких функций не отсутствовал, а подменялся родительским, что можно заметить в результате компиляции.

 

Сегодняшние стрелочные функции позволяют получить подобное поведение в ванильном JavaScript, без необходимости использования каких либо надмножеств языка и прекомпиляции кода и с честным отсутствием контекста. 

 

Вот небольшой пример, как это выглядит на JavaScript:

 

/*
  Как писали до появления стрелочных функций
*/
this.methodName = function () {
  // сохраняем ссылку на текущий контекст в переменной self
  var self = this
  setInterval(function () {
    self.innerText = ++self._elapsedSeconds
  }, 1000)
}

/*
  Используем стрелочные функции
*/
this.methodName = function () {
  setInterval(() => {
    this.innerText = ++this._elapsedSeconds
  }, 1000)
}

 

Отсутствие контекста вносит свои ограничения для этих функций:

  • Нет поддержки объекта arguments
  • Не применимы для функций связывания контекста, врод call, applybind
  • Не могут использоваться как функции конструкторы
  • Не могут быть функциями–генераторами

 

 

Синтаксис стрелочных функций позволяет также не использовать в ряде случаев ключевое слово return для возвращения значений.

 

Таким образом мы можем возвращать результат вычислений на месте: 

 

(a, b) => a + b — эквивалентно (a, b) => { return a + b }

 

Однако в случае когда функция должна вернуть объектный литерал, нужно воспользоваться одним из этих способов:

 

() => { return { a: 'b' } } — тут всё понятно

 () => ({ a: 'b' }) ← обратите внимание на оборачивающие скобки

 

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

 

 

№2 Деструктуризация

const [ x ] = [ a, b, c ]

 

Эта синтаксическая конструкция позволяет легко извлекать данные из массивов и объектных литералов. В примере выше вытаскивается первый элемент массива и сохраняется в переменную x.

 

При этом операция не мутирующая, т.е. исходный массив после извлечения не изменяется.

 

Помимо извлечения из массивов, деструктуризацию можно применять и к объектам!

 

Более того, извлечение из объектных литералов допускает переименование извлекаемых свойств, а также задание значений по умолчанию!

 


const { a: myField = 'default_value' } = { a: 'Hello world!' }

извлекаем свойство a
в константу myField
со значением по умолчанию 'default_value'


 

 

№3 Оператор многоточие (spread–operator)

const [ first, ...rest ] = [ a, b, c ]

Извлечение отдельных значений из массивов и объектов это конечно хорошо, но когда нам нужно извлечь сразу много значений (или все) пригодится оператор многоточия.

 

В примере ниже мы извлекаем первый элемент массива в константу first, а все остальные укладываем в rest

 

const [ first, ...rest ] = [ 0, 1, 2, 3, 4 ]

console.log(first) // 0

console.log(rest) // [ 1, 2, 3, 4 ]

 

И да, этот оператор поддерживает объектные литералы 👍

 

Вот так можно извлекать данные из объектов с помощью spread–оператора:

 

const employee = {
  name: 'Петя',
  age: 30,
  salary: 30_000
}

const { salary, ...person } = employee

// salary -> 30_000
// person -> { name: 'Петя', age: 30 }

 

Но и это ещё не всё!

 

Оператор имеет широкое применение в функциях!

Помните выше я указывал что у анонимных функций внутри нет arguments? Этот оператор позволяет забыть об этой магической переменной:

 

// благодаря spread-оператору мы объединяем все аргументы в массиве args
const sum = (...args) => 
    args.reduce((prev, current) => prev + current, 0)

// примеры вызова функции
sum(1, 2, 3, 4, 5) // -> 15
sum(1, 2) // -> 3

 

Вообще, этот оператор нашёл широкое применение. К примеру, теперь можно легко объединять массивы или объекты, а также распаковывать типы данных вроде Set:

 

const array1 = [ 0, 1, 2 ]
const array2 = [ 2, 3, 4 ]

// конкатенация массивов
const arrays = [ ...array1, ...array2 ] // [ 0, 1, 2, 2, 3, 4]

// лайфхак: убираем все дубли с помощью Set
const unique = [ ...(new Set(arrays)) ]

const obj1 = { a: 'a', b: 'b' }
const obj2 = { b: 'b2', c: 'c2' }

// объединение объектов
// свойства перезаписываются каждым последующим объектом!
const merged = { ...obj1, ...obj2 } // -> { a: 'a', b: 'b2', c: 'c2' }

 

 

Спасибо за внимание 😉

А какие конструкции JS больше всех нравятся тебе?

Пиши в коментах 👇, не стесняйся 👍