我正在寻找一个良好的JavaScript等价物来替代C/PHP中的printf()
或对于C#/Java程序员,String.Format()
(.NET使用 IFormatProvider
)。
我的基本要求是数字的千位分隔符格式,但能处理许多组合(包括日期)的东西会更好。
我意识到微软的Ajax库提供了一个版本的String.Format()
,但我们不想要整个框架的开销。
我正在寻找一个良好的JavaScript等价物来替代C/PHP中的printf()
或对于C#/Java程序员,String.Format()
(.NET使用 IFormatProvider
)。
我的基本要求是数字的千位分隔符格式,但能处理许多组合(包括日期)的东西会更好。
我意识到微软的Ajax库提供了一个版本的String.Format()
,但我们不想要整个框架的开销。
String.prototype.format = function(){
var final = String(this);
for(let i=0; i<arguments.length;i++){
final = final.replace(`%s${i+1}`, arguments[i])
}
return final || ''
}
console.log(("hello %s2 how %s3 you %s1").format('hi', 'hello', 'how'));
<h1 id="text">
</h1>
我使用模板字面量的方法,如下所示:
export const messages = {
foo: (arg1, arg2) => `Hello ${arg1} ${arg2}`,
bar: (arg1) => `Hello ${arg1}`,
}
来自文件:
console.log(messages.foo('Bar', 'World'))
console.log(messages.bar('Foo'))
String.prototype.format = function (args) {
var str = this;
return str.replace(String.prototype.format.regex, function(item) {
var intVal = parseInt(item.substring(1, item.length - 1));
var replace;
if (intVal >= 0) {
replace = args[intVal];
} else if (intVal === -1) {
replace = "{";
} else if (intVal === -2) {
replace = "}";
} else {
replace = "";
}
return replace;
});
};
String.prototype.format.regex = new RegExp("{-?[0-9]+}", "g");
// Sample usage.
var str = "She {1} {0}{2} by the {0}{3}. {-1}^_^{-2}";
str = str.format(["sea", "sells", "shells", "shore"]);
alert(str);
parseInt()
,就像 @hienbt88 在这里使用的一样,在性能方面会产生令人惊讶的竞争力... 我在这里对这个想法进行了整理,并尝试了一个缓存正则表达式的变体:http://jsperf.com/stringformat/6#results - parseInt()
的实现位于或接近顶部(与从此问题的答案中发布的片段中收集的其他 String.format()
版本相比)。 - fish2000修改了旧答案的代码https://dev59.com/YXRB5IYBdhLWcg3weXOX#18234317,更加高效(没有慢速RegExp)和更短
String.prototype.formatUnicorn = function () {
let str = this.toString();
if(!arguments.length) {
return;
};
const [args] = arguments;
for (const key of Object.keys(args)) {
str = str.replaceAll(`{${key}}`, args[key]);
};
return str;
};
用法:
"{test} {test_2} {test}".formatUnicorn({"test": "hello", "test_2": "world"}); // yields hello world hello
新旧版本的基准测试:https://jsben.ch/BRovx
我需要更进一步的解决方案。
一个模板,我可以重复使用它来生成字符串,不仅在声明时,还可以在执行时间的任意时刻生成。
所以我找到了这个工具:
class Texplate{
constructor(...args){
this.data = args;
}
apply(...args){
var text = "";
var i = 0, j = 0, n = this.data.length, m = args.length;
for(;i < n && j < m; i++, j++){
text += this.data[i] + args[j];
}
for (; i < n; i++){
text += this.data[i];
}
for (; j < m; j++){
text += args[j];
}
return text;
}
}
这允许创建一个文本模板,它在内部作为数组合并算法工作,从构造函数中定义的文本数组开始。
使用示例:
var Textplate example = new Texplate("Hello, ", "!");
console.log(example.apply("Frank"));
console.log(example.apply("Mary"));
console.log(example.apply());
console.log(example.apply("Frank", " Have a good day!"));
好的,首先我们将设置一些变量来使用:
const date = new Date();
const locale = 'en-us';
const wDay = date.toLocaleString(locale, {weekday: 'short'});
const month = date.toLocaleString(locale, {month: 'long'});
const year = date.toLocaleString(locale, {year: 'numeric'});
const minute = date.toLocaleString(locale, {minute: 'numeric'});
const [hour, ap] = date.toLocaleString(locale, {hour: 'numeric', hour12:true}).split(' ');
let mDay = date.toLocaleString(locale, {day: 'numeric'});
switch(mDay % 10)
{
case 1: mDay += 'st'; break;
case 2: mDay += 'nd'; break;
case 3: mDay += 'rd'; break;
default: mDay += 'th'; break;
}
现在我们已经掌握了所有这些,我们可以像这样格式化一个字符串:
const formatter = (...a) => `${a[0]}, the ${a[1]} of ${a[2]} ${a[3]} at ${a[4]}:${a[5]} ${a[6]}`;
const formatted = formatter(wDay, mDay, month, year, hour, minute, ap);
我们甚至可以为 "formatter" 函数使用命名参数:
const formatter = (wDay, mDay, month, year, hour, minute, ap) => `${wDay}, the ${mDay} of ${month} ${year} at ${hour}:${minute} ${ap}`;
const formatted = formatter(wDay, mDay, month, year, hour, minute, ap);
如果你注意到了,上面的JS模板都是回调函数的结果。如果将上面的整个代码块封装在一个预期返回格式化日期的函数中,那么很容易想象如何以同样的方式构建任意的“格式化器”函数,并从外部传入。
简而言之,如果将模板字面量放在回调函数中并使用参数作为替换,就可以重复使用它们。
这个可以与{0}、{1}和{}一起使用。
String.prototype.format = function format()
{
var msg = this;
for(var i in arguments)
msg = msg.replace(/\{\}/,arguments[i]).replace(new RegExp('\\{'+i+'\\}','g'),arguments[i]);
return msg;
}
String.prototype.repeat = function(n) {
return new Array(++n).join(this);
};
String.prototype.pad = function(requiredLength, paddingStr, paddingType) {
var n = requiredLength - this.length;
if (n) {
paddingType = paddingType ? paddingType.toLowerCase() : '';
paddingStr = paddingStr || ' ';
paddingStr = paddingStr.repeat( Math.ceil(n / paddingStr.length) ).substr(0, n);
if (paddingType == 'both') {
n /= 2;
return paddingStr.substr( 0, Math.ceil(n) ) + this + paddingStr.substr( 0, Math.floor(n) );
}
if (paddingType == 'left') {
return paddingStr + this;
}
return this + paddingStr;
}
return this;
};
// синтаксис аналогичен printf
// 'Привет, %s!'.format('мир') -> "Привет, мир!"
// '%.1s.%.1s. %s'.format('Иван', 'Иванович', 'Иванов') -> "И.И. Иванов"
String.prototype.format = function() {
var i = 0,
params = arguments;
return this.replace(/%(?:%|(?:(|[+-]+)(|0|'.+?)([1-9]\d*)?(?:\.([1-9]\d*))?)?(s|d|f))/g, function(match, sign, padding, width, precision, type) {
if (match == '%%') {
return '%';
}
var v = params[i++];
if (type == 'd') {
v = Math.round(v);
}
else if (type == 'f') {
v = v.toFixed(precision ? precision : 6);
}
if (/\+/.test(sign) && v > 0) {
v = '+' + v;
}
v += '';
if (type != 'f' && precision) {
v = v.substr(0, precision);
}
if (width) {
v = v.pad(width, padding == '' ? ' ' : padding[0] == "'" ? padding.substr(1) : padding, /-/.test(sign) ? 'right' : 'left');
}
return v;
});
};
// this.name = 'Вася';
// console.log( 'Привет, ${name}!'.template(this) );
// "Привет, Вася!"
String.prototype.template = function(context) {
return this.replace(/\$\{(.*?)\}/g, function(match, name) {
return context[name];
});
};
这是一个用于CoffeeScript的https://dev59.com/YXRB5IYBdhLWcg3weXOX#4673436 的实现。
https://gist.github.com/eces/5669361
if String.prototype.format is undefined
String.prototype.format = () ->
_arguments = arguments
this.replace /{(\d+)}/g, (match, number) ->
if typeof _arguments[number] isnt 'undefined' then _arguments[number] else match
我开始将 Java
的 String.format
(实际上是 new Formatter().format())移植到 JavaScript。最初的版本可以在以下链接中找到:
https://github.com/RobAu/javascript.string.format
您可以简单地添加JavaScript并调用StringFormat.format("%.2f", [2.4]);
等。
请注意,它尚未完成,但欢迎反馈 :)
String.padStart
。 (请参见https://dev59.com/jXE85IYBdhLWcg3wnU-p) - Nor.Z