我正在寻找一个与C/PHP printf()或C#/Java程序员String.Format()(IFormatProvider for.NET)相当的JavaScript。
目前,我的基本要求是数字的千位分隔符格式,但处理大量组合(包括日期)的格式会很好。
我意识到Microsoft的Ajax库提供了String.Format()的一个版本,但我们不希望该框架的全部开销。
我正在寻找一个与C/PHP printf()或C#/Java程序员String.Format()(IFormatProvider for.NET)相当的JavaScript。
目前,我的基本要求是数字的千位分隔符格式,但处理大量组合(包括日期)的格式会很好。
我意识到Microsoft的Ajax库提供了String.Format()的一个版本,但我们不希望该框架的全部开销。
当前回答
JavaScript中的sprintf()函数模拟为Vue过滤器和String.protype.format()扩展:
/**
* Returns a formatted string.
*
* @param template
* @param values
* @return string
*/
String.format = function (template, ...values) {
let i = -1;
function callback(exp, p0, p1, p2, p3, p4) {
if (exp === '%%') return '%';
if (values[++i] === undefined) return undefined;
exp = p2 ? parseInt(p2.substr(1)) : undefined;
let base = p3 ? parseInt(p3.substr(1)) : undefined;
let val;
switch (p4) {
case 's': val = values[i]; break;
case 'c': val = values[i][0]; break;
case 'f': val = parseFloat(values[i]).toFixed(exp); break;
case 'p': val = parseFloat(values[i]).toPrecision(exp); break;
case 'e': val = parseFloat(values[i]).toExponential(exp); break;
case 'x': val = parseInt(values[i]).toString(base ? base : 16); break;
case 'd': val = parseFloat(parseInt(values[i], base ? base : 10).toPrecision(exp)).toFixed(0); break;
}
val = typeof (val) == 'object' ? JSON.stringify(val) : val.toString(base);
let sz = parseInt(p1); /* padding size */
let ch = p1 && p1[0] === '0' ? '0' : ' '; /* isnull? */
while (val.length < sz) val = p0 !== undefined ? val + ch : ch + val; /* isminus? */
return val;
}
let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;
return template.replace(regex, callback);
}
String.prototype.format = function() {
return String.format(this, ...arguments);
}
const StringFormat = {
install: (Vue, options) => {
Vue.filter('format', function () {
return String.format(...arguments);
});
},
};
export default StringFormat;
原始答案:JavaScript相当于printf/String.Format
其他回答
我很惊讶没有人使用reduce,这是一个本机简洁而强大的JavaScript函数。
ES6(EcmaScript2015)
String.prototype.format=函数(){return[…arguments].reduce((p,c)=>p.replace(/%s/,c),this);};console.log('是%s还是%s?…不,是%s!'。格式('平面','鸟','SOman');
<ES6
function interpolate(theString, argumentArray) {
var regex = /%s/;
var _r=function(p,c){return p.replace(regex,c);}
return argumentArray.reduce(_r, theString);
}
interpolate("%s, %s and %s", ["Me", "myself", "I"]); // "Me, myself and I"
工作原理:
reduce对累加器和数组中的每个元素(从左到右)应用一个函数,以将其减少为单个值。
var _r=函数(p,c){return p.replace(/%s/,c)};控制台日志([“a”,“b”,“c”].reduce(_r,“[%s],[%s]和[%s]”)+'\n',[1,2,3].reduce(_r,“%s+%s=%s”)+'\n',[“cool”,1337,“stuff”].reduce(_r,“%s%s%s”));
我没有看到String.format变体:
String.format = function (string) {
var args = Array.prototype.slice.call(arguments, 1, arguments.length);
return string.replace(/{(\d+)}/g, function (match, number) {
return typeof args[number] != "undefined" ? args[number] : match;
});
};
JavaScript中的sprintf()函数模拟为Vue过滤器和String.protype.format()扩展:
/**
* Returns a formatted string.
*
* @param template
* @param values
* @return string
*/
String.format = function (template, ...values) {
let i = -1;
function callback(exp, p0, p1, p2, p3, p4) {
if (exp === '%%') return '%';
if (values[++i] === undefined) return undefined;
exp = p2 ? parseInt(p2.substr(1)) : undefined;
let base = p3 ? parseInt(p3.substr(1)) : undefined;
let val;
switch (p4) {
case 's': val = values[i]; break;
case 'c': val = values[i][0]; break;
case 'f': val = parseFloat(values[i]).toFixed(exp); break;
case 'p': val = parseFloat(values[i]).toPrecision(exp); break;
case 'e': val = parseFloat(values[i]).toExponential(exp); break;
case 'x': val = parseInt(values[i]).toString(base ? base : 16); break;
case 'd': val = parseFloat(parseInt(values[i], base ? base : 10).toPrecision(exp)).toFixed(0); break;
}
val = typeof (val) == 'object' ? JSON.stringify(val) : val.toString(base);
let sz = parseInt(p1); /* padding size */
let ch = p1 && p1[0] === '0' ? '0' : ' '; /* isnull? */
while (val.length < sz) val = p0 !== undefined ? val + ch : ch + val; /* isminus? */
return val;
}
let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;
return template.replace(regex, callback);
}
String.prototype.format = function() {
return String.format(this, ...arguments);
}
const StringFormat = {
install: (Vue, options) => {
Vue.filter('format', function () {
return String.format(...arguments);
});
},
};
export default StringFormat;
原始答案:JavaScript相当于printf/String.Format
我使用模板文字方法,如下所示:
export const messages = {
foo: (arg1, arg2) => `Hello ${arg1} ${arg2}`,
bar: (arg1) => `Hello ${arg1}`,
}
从文件中:
console.log(messages.foo('Bar', 'World'))
console.log(messages.bar('Foo'))
好的,首先我们将设置一些要使用的变量:
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);
我们甚至可以为“格式化程序”函数使用命名参数:
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模板都是回调的结果。如果上面的整段代码都封装在一个预期返回格式化日期的函数中,那么不难想象如何以相同的方式构造一个可以从外部传入的任意“格式化程序”函数。
tl;dr如果将模板文本放在回调中并使用args作为替换,则可以重用它们。