- PVSM.RU - https://www.pvsm.ru -

Строковая интерполяция. Сказка-быль

Постановка задачи

Совершенно случайно я превратился из питониста в JS-разработчика, и на мою хрупкую детскую психику обрушился непосильный груз вещей, которых в JS нет. Например, нет удобного форматирования строк. На питоне можно написать:

'hello, %(thing)s' % {'thing': 'world'}

Или вот так:

'hello, {thing}'.format(**{'thing': 'world'})

Строковая интерполяция. Сказка быль

Ближайший аналог в JS — конкатенация (operator +), которая очень плохо масштабируется с увеличением длины строки, да еще и выглядит безобразно до предела:

'<div class="input-append"><input type="text" name="username" '+
'id="signup_username" placeholder="'+placeholder+'"><input '+
'type="hidden" name="password" value="'+generated+'"><button '+
...

По возможности хотелось бы этого избежать.

Jeremy Ashkenas, когда разрабатывал CoffeeScript, также обратил на эту особенность JS внимание, и случайно диалект PHP:

"hello, #{document.cookie}"

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

Мне в этой штуке нравится похожий на Ruby синтаксис, но не нравится все остальное, особенно выполнение произвольного кода внутри строки. Таким образом постановка задачи:

– написать функцию
– которая подставляет переменные в строку
– загруженную из файла
– не PHP

Поиск решения

Обычно в таких случаях используют готовые библиотеки, более того, в NPM по слову template находится более двух тысяч пакетов.

В самом деле, mustache или lodash (underscore.js) работают превосходно, но… очень медленно: 10-20 мкс на одну подстановку. Не предел мечтаний ни в коем случае, особенно когда «продвинутый» функционал вроде циклов и фильтров совершенно не нужен.

А конкатенация, хоть и выглядит страшно, как звериный оскал коллективизма, работает все-таки в 10-30 раз быстрее. Таким образом, мы добавляем к постановке задачи:

– транслируется в конкатенацию
– и работает очень быстро

Вот теперь по этой спецификации можно изобретать велосипед. Because why not.

Что получилось

У меня получилась вот такая штука: Ruby-like simple string interpolation (GitHub) [1]

В ней 9 строк кода, и она выполняет миллион триста тысяч подстановок в секунду (около 0,77 мкс на подстановку) на той же машине, где mustache делает 130 тысяч, а lodash/underscore 45 тысяч подстановок в секунду.

var hello = fmt('hello, #{thing}')
hello({thing: 'world'})
// -> hello, world

Вывод: за счет отказа от сложных функций шаблонизатора (циклы, условные выражения) было достигнуто ускорение в 10-30 раз по сравнению с популярными библиотеками, не прибегая к выполнению произвольного кода в шаблоне.

Rssi.js можно установить из npm очевидной командой npm install rssi, поддерживается также Bower (bower install rssi); на стороне клиента можно использовать AMD (RequireJS), а можно не использовать.

Строковая интерполяция. Сказка быль

Спасибо за прочитывание этого не очень связного текста! Пишите патчи, господа хорошие, и до новых встреч.

Автор: printf

Источник [2]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/42244

Ссылки в тексте:

[1] Ruby-like simple string interpolation (GitHub): https://github.com/mvasilkov/rssi/blob/master/rssi.js

[2] Источник: http://habrahabr.ru/post/192124/