CSS-live.ru

ES6: возможности литерала объекта изнутри

Перевод статьи ES6 Object Literal Features in Depth  с сайта ponyfoo.com, опубликовано на css-live.ru с разрешения автора — Николаса Беваквы.

И снова «ES6 изнутри». Если вы в этом цикле статей впервые, то советую изучить деструктирование, литералы шаблона, стрелочные функции или операторы расширения и оставшиеся параметры. Сегодня предлагаю познакомиться с литералами объекта в ES6. «Ну уж их-то и сейчас можно использовать» — скажете вы — литералы объекта тянутся еще аж с ES3. Эта статья про новинки ES6 для литералов объекта.

Как и в прошлых статьях, рекомендую вам установить Babel и повторять за мной, копируя примеры с помощью REPL, либо командной строки babel-node и файла. Это поможет гораздо лучше усвоить идеи, обсуждаемые в серии. Если вы не из тех, кто любит устанавливать что-либо на свой компьютер, то вам есть смысл залезть на CodePen и кликнуть иконку с шестерёнкой для JavaScript — у него есть препроцессор Babel, который с лёгкостью позволяет опробовать ES6.

Вперёд к неизведанному!

Сокращённые записи значений свойства

Всякий раз, когда имя свойства совпадает с его значением, то последнее можно опустить, в ES6 оно подставляется неявно.

var foo = 'bar'
var baz = { foo }
console.log(baz.foo)
// <- 'bar'

В показанном ниже снипете я воспроизвел часть localStorage в памяти в качестве полифилла. Это паттерн, который я применял несметное число раз в своём коде.

var ms = {}

function getItem (key) {
  return key in ms ? ms[key] : null
}

function setItem (key, value) {
  ms[key] = value
}

function clear () {
  ms = {}
}

module.exports = {
  getItem: getItem,
  setItem: setItem,
  clear: clear
}

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

  • Не приходится увеличивать отступ
  • Публичный API выделяется
  • Труднее получить сильно связанные методы
  • Легче для понимания

С ES6 в этот список можно добавить ещё один пункт — с помощью сокращённых записей значения свойства можно еще упростить экспорт. Если имя свойства совпадает с его значением, то последнее можно опустить. Таким образом, module.exports из кода выше становится:

module.exports = { getItem, setItem, clear }

Другое дело!

Динамические имена свойства

Мы уже обсуждали динамические имена свойств в статье про деструктирование. А вот очень типичный для меня пример:

var foo = 'bar'
var baz = {}
baz[foo] = 'ponyfoo'
console.log(baz)
// <- { bar: 'ponyfoo' }

Вместо обычного имени свойства, динамические имена свойств позволяют писать выражения, обёрнутые в квадратные скобки. Результат выражения, каким бы он ни был, станет именем свойства.

var foo = 'bar'
var baz = { [foo]: 'ponyfoo' }
console.log(baz)
// <- { bar: 'ponyfoo' }

У динамических имен свойства есть ограничение — с ними нельзя использовать сокращённое выражение. Я думаю, причина в том, что сокращенное выражение должно быть простым «сахарком», применяющимся во время компиляции.

var foo = 'bar'
var bar = 'ponyfoo'
var baz = { [foo] }
console.log(baz)
// <- SyntaxError

При всём сказанном, думаю, вот наиболее типичное применение. Тут код проще, поскольку не нужны три лишних действия — заводить переменную foo, присваивать значение foo[type] и возвращать foo. Вместо этого можно сделать всё это в одном операторе.

function getModel (type) {
  return {
    [type]: {
      message: 'превед, йа пёсег',
      date: new Date()
    }
  }
}

То что надо. Что же ещё?

Определения методов

Обычно в ES5 объявление методов происходит так:

var foo = {
  bar: function (baz) {
  }
}

Тогда как синтаксис геттеров и сеттеров не требует ключевого слова function. Это просто вытекает из контекста.

var cart = {
  _wheels: 4,
  get wheels () {
    return this._wheels
  },
  set wheels (value) {
    if (value < this._wheels) {
      throw new Error('Эй, верни на место!')  
    }
    this._wheels = value
  }
}

Начиная с ES6, можно объявлять обычные методы с похожим синтаксисом, разница лишь в отсутствии перед ними get или set.

var cart = {
  _wheels: 4,
  get wheels () {
    return this._wheels
  },
  set wheels (value) {
    if (value < this._wheels) {
      throw new Error('Эй, верни на место!')  
    }
    this._wheels = value
  },
  dismantle () {
    this._wheels = 0
    console.warn(`вы еще за это заплатите!`)
  }
}

По-моему, здорово, что методы настолько сблизились с геттерами и сеттерами. Что до меня, то я не часто использую этот синтаксис, поскольку мне нравится именовать функции и отделять их от их объекта-хозяина, как я рассказывал в разделе про сокращённую запись. Однако, в некоторых случаях это всё же полезно, особенно при объявлении «классов» — если вы интересуетесь чем-то подобным.

P.S. Это тоже может быть интересно:

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.