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

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

Совершенно случайно я превратился из питониста в 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)

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

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

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

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

ссылка на оригинал статьи http://habrahabr.ru/post/192124/

Добавить комментарий

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