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. Это тоже может быть интересно:
None Found