Pull to refresh

Comments 48

Я добавлю свой вариант:

var thing = 'world!';
['Hello ', thing].join("");
Тем, кому не понравился комментарий добавлю:

String.prototype.format = function() {
	var i = -1, args = arguments;
	
	return this.replace(/#\{(.*?)\}/g, function(one, two) {
		return (typeof args[0] == 'object')?args[0][two]:args[++i];
	});
}

var thing = 'world!';

console.log(
	'hello #{1} - #{2}'.format(thing, 'two!'),
	'hello #{wrd} - #{2}'.format({'wrd': thing, '2': 'two!'})
);
Конечно круто, но использовать я бы не стал из-за обилия регулярок, в основном они — самая медленная операция в функции.
Кстати, в своём бы посте я бы вообще убрал регулярку. И сделал так:

String.prototype.format = function() {
	var i = 0, args = arguments, regular = /#\{(.*?)\}/g, func = function(one, two) {
		return (typeof args[0] == 'object')?args[0][two]:args[i++];
	}
	
	return this.replace(regular, func);
}

String.prototype.format2 = function() {
	var i = 0
		, k = 0
		, last_k = 0 
		, type = typeof arguments[0] == 'object'
		, len = this.length
		, open = false
		, ret = '';
	
	for(;k < len;k++) {
		if(this[k] == '#' && this[k+1] != undefined && this[k+1] == '{') {
			last_k = open = k += 2;
		}
		else if(open && this[k] == '}') {
			ret += type ? arguments[0][this.substring(last_k, k)] : arguments[i++];
			open = false;
		}
		else if(!open) {
			ret += this[k];
		}
	}		
	return ret;
}

// https://github.com/lampaa/JSTF
function RunTest(a,b,c){var d=console;d.time(c);for(var i=0;i<b;i++){a(i)}d.timeEnd(c)}
	
var thing = 'world!';
	
RunTest(function(cycleNum) {
	'hello #{1} - #{2}'.format(thing, 'two!');
	'hello #{wrd} - #{2}'.format({'wrd': thing, '2': 'two!'});
}, 400000, '1');

RunTest(function(cycleNum) {
	'hello #{1} - #{2}'.format2(thing, 'two!');
	'hello #{wrd} - #{2}'.format2({'wrd': thing, '2': 'two!'});
}, 400000, '2');


Хром:
1: 4237.000ms
2: 3662.000ms

В лисе всё с точностью наборот.
UFO just landed and posted this here
UFO just landed and posted this here
Ну там много чего есть, циклы, функции.
Для полноценных шаблонов (сайтов, например) я обычно mustache как раз и использую.
Совершенно случайно я превратился из питониста в JS-разработчика

Как же это Вас угораздило? )
на одних бэкендах далеко не уедешь…
В CoffeeScript подстановка переменных в строку сделана аналогично Ruby, PHP тут не причем.
Имелся в виду доступ к глобальным объектам из шаблона, у меня почему-то первая ассоциация с php.
«hello, #{document.cookie}»

Очень печально, что такая же хрень попадет и в ES6:(
Потому что идеальный синтаксис для этого — как в python, а не как в уродском php.
А вот это я бенчмаркнуть, конечно, забыл. Спасибо, добавлю.

Эх, была бы sprintf() нативной — все проблемы решились бы сами собой.
Для любителей стрелять межконтинентальными баллистическими ракетами по воробьям: Vash.js

<p>How are you @model.name? Today is a sunny day on the planet Gunsmoke.</p>

<ul class="@(model.active ? 'highlight' : '')">
    @model.forEach(function(m){
        <li>m.name</li>
    })
</ul>


У этой библиотеки, конечно, несколько иная область применения, но как синтаксический сахар все же интересно.

<offtop>
Думаю попробовать использовать в самопальной CMS для создания страниц с привязанными данными
</offtop>
Вам pull request.

Немного перемудрили с «JSON.stringify» — это лишнее; кеширование регекспа даст +5% к производительности; и не предавайте забвению точку с запятой, что может сыграть злую шутку в джаваскрипте;.
Спасибо за патч. Тесты запускаются (GNU) make. В данном случае они даже не запускаются.

Никакой злой шутки правильная расстановка точек с запятой в JS сыграть не может; в коде стоят все нужные точки с запятой.

Кеширование регулярки завтра попробую измерить, спасибо.
Ваш код не содержал ни одной ;, поэтому позволил себе напомнить) Все же, их использование является таким себе правилом хорошего тона.
Как злая шутка:
var b = 1, c = 1, a = b + c
(1+2).toString()

Тесты, каюсь, не запускал, правил онлайн. Падают скорее всего потому, что я изменил названия моих любимых переменных foo и bar. Попробую залить пачсет позже.

Кстати, вчера на заметил, но предпочтительнее использовать obj.hasOwnProperty("' + bar + '") для проверки наличия проперти.
«Правилом хорошего тона» является при работе с заимствованным кодом сохранять стиль кода. Про расстановку никчемных знаков препинания ничего не слышал, хотя, безусловно, можно писать и так:
;;var a = 9;;;

Как я и писал выше, в коде расставлены все нужные точки с запятой. Ненужные, в полном соответствии со стандартом языка, не расставлены.
Это все Phyton виноват.

Хозяин — барин, но порекомендую habrahabr.ru/post/136860/

Тесты поправил, JSON.stringify вернул (увидел, что обрабатываете "\n" в строке. В этом случае — да, использование JSON.stringify оправдано, но не забывайте о старых ИЕ — им ничего неизвестно о JSON)
В статье по ссылке хорошо описаны несколько «злых шуткок», но, в тоже время, она оправдывает ";" в начале строк. На мой взгляд, это конечная стадия пути «расставляем везде -> расставляем нужные -> расставляем на всякий случай в начале». Читать такой код невозможно, надеюсь, и на ваш взгляд тоже.

Чтобы расставить точки с запятой над i. Я ставлю знаки везде в конце строк — это исключает вероятность синтаксических ошибок при минификации скрипта + считаю, что такой код удобнее читать + это удобная привычка для С-like языков, коих много.
Позволю себе процитировать статью, о которой мы говорим:
Пишите код, как хотите. Мне нет ни малейшего дела.
Пожалуй, вряд ли мы сможем обсудить «вероятность синтаксических ошибок при минификации скрипта». Ошибочно считать, что кому-то есть дело до чужого кода.
А зачем обсуждать нулевую вероятность чего-либо? При минификации этого скрипта не происходит синтаксических ошибок, если не использовать сломанный минификатор. Google Closure, UglifyJS и другие распространенные программы превосходно справляются с валидным JS, как и все графические браузеры (даже, не к ночи будь помянут, MSIE6), Node.js и другие JS-окружения. Проверьте и убедитесь сами.

Именно для этого существует стандарт языка.
если не использовать сломанный минификатор

Неизвестно кто какой минификатор будет использовать для моего кода, поэтому мне не сложно обезопасить себя от недоразумений, даже если они и случались с нулевой вероятностью два раза.
Да, в старых браузерах JSON3.js или аналог нужно подключать отдельно.

Спасибо, я читал этот пост в оригинале пару лет назад. Более того, он полностью подтверждает мою позицию. Возможно, вы хотели запостить ссылку на какой-то другой, опровергающий пост.
Статьей хотел пояснить, что такая позиция может привести к затрудненной читаемости кода того же npm. Потом уже понял, что это и был ваш style-guide. Nevermind)
К слову, говорить о том, что запись вида:

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

лучше, чем:

'hello, ' + thing + 's'

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

Например, кошмарные конструкции вида ..."'+str+'"
Мне сложно представить, что кому-то активно нравится набирать эти хитросплетения кавычек (а это еще очень простой случай):

'<a href="'+url+'" class="btn btn-'+button_type+'" rel="goto-'+target+'">'+link_text+'</a>'


И то же самое по версии CoffeeScript, ошибиться просто негде:

"<a href='#{url}' class='btn btn-#{button_type}' rel='goto-#{target}'>#{link_text}</a>"
Мой комментарий был о том, что записывать переменную непосредственно в требуемое место строки проще, чем записывать в требуемое место строки сначала макрос, а потом, в конце строки, записывать уже переменную, которая будет заменять этот макрос (если только такое поведение не требуется специально). А в случае, когда переменных много, — особенно. Вы же сейчас привели просто два различных способа записи именно первого случая.

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

> «И то же самое по версии CoffeeScript, ошибиться просто негде:»
Ошибиться можно, например, вот так (в коде две ошибки):
"<a href='#{url}' class='btn btn-# {button_type}' rel='goto-#{target}'>#{link_text)</a>"
В редакторе с подсветкой кода ошибки достаточно заметны:
"<a href='#{url}' class='btn btn-# {button_type}' rel='goto-#{target}'>#{link_text)</a>"

Но да, безусловно, ошибиться можно.

Про нравится / не нравится не стану спорить, мне просто не встречалась такая точка зрения.
Самая близкая по краткости запись этого выражения, наверное, такая:
'test #{foo} and #{bar}'.replace(/#{(\w+)}/g, function(s,m) {return {foo:42, bar:43}[m]});
Я думал, может сделать это так, как сделано в QString (из библиотеки Qt, C++). Тогда шаблонизация будет вида:

// Plain one
return "Hello, %1".arg("world!");

// Complicated one
return "Hello, #{world}".arg({'world' : 'world!'});


Я не большой мастак JS, но насколько я знаю, можно добавить эту функцию в прототип String. А вообще, стоит ли запилить такую штуку?
'<div class="input-append"><input type="text" name="username" '+
'id="signup_username" placeholder="'+placeholder+'"><input '+
'type="hidden" name="password" value="'+generated+'"><button '+
...

Хотелось бы услышать наилучшее решение этой проблемы. Решения, такие как загрузка внешних файлов (шаблонов), или, подключения библиотек, с весом в over100kb — не рассматриваю (не потому что это плохо, просто мне так не подходит).
Комментарий выше, например. 1 функция в String.prototype и вуаля! Если хотите, наклепаю
Имеется ввиду именно многострочность строки
Многострочность можно делать как в Си, это не очень хороший способ, но работает в современных браузерах и Node.js:
str = "FFFFFFFFFFFF\
FFFFFFFFFFFFUUUU\
UUUUUUUUuuuuuuuu"

Или использовать CoffeeScript, например.

А почему загрузка файлов не подходит? Я обычно именно это делаю, когда есть куча html или другой фигни, которой в коде быть совершенно необязательно.
Даже не знаю, побаиваюсь почему-то. Фобия так скажем. Про \ знаю — не устраивает.
UFO just landed and posted this here
UFO just landed and posted this here
Шаблонизация это зачастую DOM, но не всегда. Шаблонизатор должен решать обобщённую задачу генерации строки по шаблону. Можно генерить SVG и прочие XMLи, можно генерить таблицы стилей, можно генерить вообще отчёты в текстовом файле. И всё это не конструируя DOM.
UFO just landed and posted this here
Sign up to leave a comment.

Articles