JavaScript эквивалентен printf / String.Формат
Я ищу хороший JavaScript-эквивалент C / PHP printf()
или для программистов C# / Java,String.Format()
(IFormatProvider
для .NET).
мое основное требование-формат тысяч разделителей для чисел на данный момент, но что-то, что обрабатывает множество комбинаций (включая даты), было бы хорошо.
Я понимаю Microsoft Ajax библиотека предоставляет версии String.Format()
, но нам не нужны все накладные расходы этой структуры.
30 ответов
Edit: из ES6 вы можете использовать строки шаблона:
let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!
посмотреть Ким!--7-->ответ ниже для деталей.
оригинальный ответ:
попробовать sprintf () для JavaScript.
обновление хорошо, если вы действительно хотите сделать простой метод формата самостоятельно, не делайте замены последовательно, а делайте их одновременно.
потому что большинство других предложений, которые упоминаются сбой, когда строка замены предыдущей замены также содержит последовательность форматов, подобную этой:
"{0}{1}".format("{1}", "{0}")
обычно вы ожидаете, что выход будет {1}{0}
но фактический выход составляет {1}{1}
. Так что сделайте одновременно замену, а не как в предложение fearphage.
основываясь на ранее предложенных решениях:
// First, checks if it isn't implemented yet.
if (!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
}
"{0} is dead, but {1} is alive! {0} {2}".format("ASP", "ASP.NET")
выходы
ASP мертв, но ASP.NET жив! ASP {2}
если вы предпочитаете не изменять С:
if (!String.format) {
String.format = function(format) {
var args = Array.prototype.slice.call(arguments, 1);
return format.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
}
дает вам гораздо более знакомы:
String.format('{0} is dead, but {1} is alive! {0} {2}', 'ASP', 'ASP.NET');
С тем же результатом:
ASP мертв, но ASP.NET жив! ASP {2}
это смешно, потому что переполнение стека на самом деле имеет свою собственную функцию форматирования для String
прототип под названием formatUnicorn
. Попробуй! Перейдите в консоль и введите что-то вроде:
"Hello, {name}, are you feeling {adjective}?".formatUnicorn({name:"Gabriel", adjective: "OK"});
вы получаете этот вывод:
Hello, Gabriel, are you feeling OK?
вы можете использовать объекты, массивы и строки в качестве аргументов! Я получил его код и переработал его, чтобы создать новую версию String.prototype.format
:
String.prototype.formatUnicorn = String.prototype.formatUnicorn ||
function () {
"use strict";
var str = this.toString();
if (arguments.length) {
var t = typeof arguments[0];
var key;
var args = ("string" === t || "number" === t) ?
Array.prototype.slice.call(arguments)
: arguments[0];
for (key in args) {
str = str.replace(new RegExp("\{" + key + "\}", "gi"), args[key]);
}
}
return str;
};
Примечание умная Array.prototype.slice.call(arguments)
звоните -- это означает, что если вы бросаете аргументы, которые являются строками или числами, а не одним объектом JSON-стиля, вы получаете c#'s String.Format
поведение почти в точности.
"a{0}bcd{1}ef".formatUnicorn("foo", "bar"); // yields "aFOObcdBARef"
потому что Array
' s slice
заставит все, что в arguments
на Array
, было ли это изначально или нет, и key
будет индексом (0, 1, 2...) каждого элемента массива, приведенного в строку (например, "0", so "\{0\}"
для вашего первого шаблона regexp).
аккуратно.
форматирование чисел в JavaScript
я попал на эту страницу вопроса, надеясь найти, как число в формате в JavaScript, без введения еще одной библиотеки. Вот что я нашел:--15-->
округление чисел с плавающей запятой
в эквиваленте sprintf("%.2f", num)
в JavaScript, кажется num.toFixed(2)
, какие форматы num
до 2 знаков после запятой с округлением (но см. комментарий @ars265 о Math.round
ниже.)
(12.345).toFixed(2); // returns "12.35" (rounding!)
(12.3).toFixed(2); // returns "12.30" (zero padding)
экспоненциальная форма
в эквиваленте sprintf("%.2e", num)
is num.toExponential(2)
.
(33333).toExponential(2); // "3.33e+4"
шестнадцатеричные и другие основания
чтобы напечатать номера в базе B, попробуйте num.toString(B)
. JavaScript поддерживает автоматическое преобразование в и из баз 2 через 36 (кроме того, некоторые браузеры имеют ограниченная поддержка кодирования base64).
(3735928559).toString(16); // to base 16: "deadbeef"
parseInt("deadbeef", 16); // from base 16: 3735928559
Ссылка Страницы
быстрый учебник по номеру JS форматирование
справочная страница Mozilla для toFixed () (со ссылками на toPrecision (), toExponential (), toLocaleString (),...)
из ES6 вы можете использовать шаблон строки:
let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!
имейте в виду, что строки шаблона являются в окружении backticks вместо (один) цитаты.
для дальнейшего информация:
https://developers.google.com/web/updates/2015/01/ES6-Template-Strings
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings
Примечание.: Проверьте сайт mozilla, чтобы найти список поддерживаемых браузеров.
jsxt, Zippo
этот вариант лучше подходит.
String.prototype.format = function() {
var formatted = this;
for (var i = 0; i < arguments.length; i++) {
var regexp = new RegExp('\{'+i+'\}', 'gi');
formatted = formatted.replace(regexp, arguments[i]);
}
return formatted;
};
С помощью этой опции я могу заменить такие строки:
'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP');
С кодом второй {0} не будет заменен. ;)
Я использую эту простую функцию:
String.prototype.format = function() {
var formatted = this;
for( var arg in arguments ) {
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
}
return formatted;
};
Это очень похоже на string.формат:
"{0} is dead, but {1} is alive!".format("ASP", "ASP.NET")
здесь минимальный реализация sprintf в JavaScript: он делает только "%s" и "%d", но я оставил место для его расширения. Это бесполезно для OP, но другие люди, которые натыкаются на эту тему, исходящую от Google, могут извлечь из этого выгоду.
function sprintf() {
var args = arguments,
string = args[0],
i = 1;
return string.replace(/%((%)|s|d)/g, function (m) {
// m is the matched format, e.g. %s, %d
var val = null;
if (m[2]) {
val = m[2];
} else {
val = args[i];
// A switch statement so that the formatter can be extended. Default is %s
switch (m) {
case '%d':
val = parseFloat(val);
if (isNaN(val)) {
val = 0;
}
break;
}
i++;
}
return val;
});
}
пример:
alert(sprintf('Latitude: %s, Longitude: %s, Count: %d', 41.847, -87.661, 'two'));
// Expected output: Latitude: 41.847, Longitude: -87.661, Count: 0
В отличие от аналогичных решений в предыдущих ответах, это делает все замены за один, поэтому он не заменит части ранее замененные значения.
на узел.js нет util.format
, который имеет функции printf функции:
util.format("%s world", "Hello")
Я удивлен, что никто не использовал reduce
, это родная сжатая и мощная функция JavaScript.
ES6 (EcmaScript2015)
String.prototype.format = function() {
return [...arguments].reduce((p,c) => p.replace(/%s/,c), this);
};
console.log('Is that a %s or a %s?... No, it\'s %s!'.format('plane', 'bird', 'SOman'));
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"
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"
как работает:
уменьшить применяет функцию к аккумулятору и каждому элементу в массиве (слева направо), чтобы уменьшить его до одного значения.
var _r= function(p,c){return p.replace(/%s/,c)};
console.log(
["a", "b", "c"].reduce(_r, "[%s], [%s] and [%s]") + '\n',
[1, 2, 3].reduce(_r, "%s+%s=%s") + '\n',
["cool", 1337, "stuff"].reduce(_r, "%s %s %s")
);
JavaScript программисты могут использовать строку.прототип.sprintf на https://github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js. Ниже приведен пример:
var d = new Date();
var dateStr = '%02d:%02d:%02d'.sprintf(
d.getHours(),
d.getMinutes(),
d.getSeconds());
+1 Zippo за исключением того, что тело функции должно быть как показано ниже или иначе оно добавляет текущую строку на каждой итерации:
String.prototype.format = function() {
var formatted = this;
for (var arg in arguments) {
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
}
return formatted;
};
добавлять к zippoxer
ответ, я использую эту функцию:
String.prototype.format = function () {
var a = this, b;
for (b in arguments) {
a = a.replace(/%[a-z]/, arguments[b]);
}
return a; // Make chainable
};
var s = 'Hello %s The magic number is %d.';
s.format('world!', 12); // Hello World! The magic number is 12.
у меня также есть версия без прототипа, которую я использую чаще для ее Java-подобного синтаксиса:
function format() {
var a, b, c;
a = arguments[0];
b = [];
for(c = 1; c < arguments.length; c++){
b.push(arguments[c]);
}
for (c in b) {
a = a.replace(/%[a-z]/, b[c]);
}
return a;
}
format('%d ducks, 55 %s', 12, 'cats'); // 12 ducks, 55 cats
обновление ES 2015
все новые интересные вещи в ES 2015 делает это намного проще:
function format(fmt, ...args){
return fmt
.split("%%")
.reduce((aggregate, chunk, i) =>
aggregate + chunk + (args[i] || ""), "");
}
format("Hello %%! I ate %% apples today.", "World", 44);
// "Hello World, I ate 44 apples today."
я подумал, что, поскольку это, как и старые, на самом деле не анализирует буквы, он может также просто использовать один токен %%
. Это имеет преимущество быть очевидным и не затрудняя использование одного %
. Однако, если вам нужно %%
по какой-то причине вам нужно будет заменить его на себя:
format("I love percentage signs! %%", "%%");
// "I love percentage signs! %%"
очень элегантный:
String.prototype.format = function (){
var args = arguments;
return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (curlyBrack, index) {
return ((curlyBrack == "{{") ? "{" : ((curlyBrack == "}}") ? "}" : args[index]));
});
};
// Usage:
"{0}{1}".format("{1}", "{0}")
Я добавлю свои собственные открытия, которые я нашел, так как я спросил:
- number_format (для тысяч разделителя/форматирования валюты)
- функции sprintf (тот же автор, что и выше)
к сожалению, sprintf не обрабатывает форматирование тысяч разделителей, такое как строковый формат .NET.
Я использую небольшую библиотеку под названием строку.формат для JavaScript который поддерживает большинство возможностей строки формата (включая формат чисел и дат) и использует синтаксис .NET. Сам скрипт меньше 4 КБ, поэтому он не создает больших накладных расходов.
Если вы хотите обработать разделитель тысяч, вы действительно должны использовать toLocaleString () из JavaScript класс, так как он будет форматировать строку для пользователя области.
JavaScript дата класс может форматировать локализованные даты и время.
Я хочу поделиться своим решением для "проблемы". Я не заново изобрел колесо, но пытается найти решение, основанное на том, что уже делает JavaScript. Преимущество заключается в том, что вы получаете все неявные преобразования бесплатно. Установка свойства prototype $ of String дает очень приятный и компактный синтаксис (см. примеры ниже). Возможно, это не самый эффективный способ, но в большинстве случаев он не должен быть супер оптимизирован.
String.form = function(str, arr) {
var i = -1;
function callback(exp, p0, p1, p2, p3, p4) {
if (exp=='%%') return '%';
if (arr[++i]===undefined) return undefined;
exp = p2 ? parseInt(p2.substr(1)) : undefined;
var base = p3 ? parseInt(p3.substr(1)) : undefined;
var val;
switch (p4) {
case 's': val = arr[i]; break;
case 'c': val = arr[i][0]; break;
case 'f': val = parseFloat(arr[i]).toFixed(exp); break;
case 'p': val = parseFloat(arr[i]).toPrecision(exp); break;
case 'e': val = parseFloat(arr[i]).toExponential(exp); break;
case 'x': val = parseInt(arr[i]).toString(base?base:16); break;
case 'd': val = parseFloat(parseInt(arr[i], base?base:10).toPrecision(exp)).toFixed(0); break;
}
val = typeof(val)=='object' ? JSON.stringify(val) : val.toString(base);
var sz = parseInt(p1); /* padding size */
var ch = p1 && p1[0]=='0' ? '0' : ' '; /* isnull? */
while (val.length<sz) val = p0 !== undefined ? val+ch : ch+val; /* isminus? */
return val;
}
var regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;
return str.replace(regex, callback);
}
String.prototype.$ = function() {
return String.form(this, Array.prototype.slice.call(arguments));
}
вот несколько примеры:
String.format("%s %s", [ "This is a string", 11 ])
console.log("%s %s".$("This is a string", 11))
var arr = [ "12.3", 13.6 ]; console.log("Array: %s".$(arr));
var obj = { test:"test", id:12 }; console.log("Object: %s".$(obj));
console.log("%c", "Test");
console.log("%5d".$(12)); // ' 12'
console.log("%05d".$(12)); // '00012'
console.log("%-5d".$(12)); // '12 '
console.log("%5.2d".$(123)); // ' 120'
console.log("%5.2f".$(1.1)); // ' 1.10'
console.log("%10.2e".$(1.1)); // ' 1.10e+0'
console.log("%5.3p".$(1.12345)); // ' 1.12'
console.log("%5x".$(45054)); // ' affe'
console.log("%20#2x".$("45054")); // ' 1010111111111110'
console.log("%6#2d".$("111")); // ' 7'
console.log("%6#16d".$("affe")); // ' 45054'
на проект PHPJS написал реализации JavaScript для многих функций PHP. Так как PHP sprintf()
функция в основном такая же, как c printf()
, их реализация JavaScript этого должно удовлетворять ваши потребности.
Я использую этот:
String.prototype.format = function() {
var newStr = this, i = 0;
while (/%s/.test(newStr))
newStr = newStr.replace("%s", arguments[i++])
return newStr;
}
тогда я называю это:
"<h1>%s</h1><p>%s</p>".format("Header", "Just a test!");
одна очень немного другая версия, та, которую я предпочитаю (этот использует маркеры {xxx}, а не нумерованные аргументы {0}, это гораздо более самодокументировано и подходит для локализации намного лучше):
String.prototype.format = function(tokens) {
var formatted = this;
for (var token in tokens)
if (tokens.hasOwnProperty(token))
formatted = formatted.replace(RegExp("{" + token + "}", "g"), tokens[token]);
return formatted;
};
вариация будет:
var formatted = l(this);
который сначала вызывает функцию локализации l ().
у меня есть решение, очень близкое к Питеру,но оно касается числа и объекта.
if (!String.prototype.format) {
String.prototype.format = function() {
var args;
args = arguments;
if (args.length === 1 && args[0] !== null && typeof args[0] === 'object') {
args = args[0];
}
return this.replace(/{([^}]*)}/g, function(match, key) {
return (typeof args[key] !== "undefined" ? args[key] : match);
});
};
}
возможно, было бы еще лучше иметь дело со всеми случаями deeps, но для моих нужд это просто отлично.
"This is an example from {name}".format({name:"Blaine"});
"This is an example from {0}".format("Blaine");
PS: эта функция очень круто, если вы используете переводы в шаблонах фреймворков, как AngularJS:
<h1> {{('hello-message'|translate).format(user)}} <h1>
<h1> {{('hello-by-name'|translate).format( user ? user.name : 'You' )}} <h1>
где en.JSON-это что-то вроде
{
"hello-message": "Hello {name}, welcome.",
"hello-by-name": "Hello {0}, welcome."
}
для тех, кто любит узел.JS и util.format
feature, я только что извлек его в свою ванильную форму JavaScript (только с функциями, которые util.формат используется):
exports = {};
function isString(arg) {
return typeof arg === 'string';
}
function isNull(arg) {
return arg === null;
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isBoolean(arg) {
return typeof arg === 'boolean';
}
function isUndefined(arg) {
return arg === void 0;
}
function stylizeNoColor(str, styleType) {
return str;
}
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][3] + 'm';
} else {
return str;
}
}
function isFunction(arg) {
return typeof arg === 'function';
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isSymbol(arg) {
return typeof arg === 'symbol';
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\'")
.replace(/\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value)) {
// Format -0 as '-0'. Strict equality won't distinguish 0 from -0,
// so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 .
if (value === 0 && 1 / value < 0)
return ctx.stylize('-0', 'number');
return ctx.stylize('' + value, 'number');
}
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
// es6 symbol primitive
if (isSymbol(value))
return ctx.stylize(value.toString(), 'symbol');
}
function arrayToHash(array) {
var hash = {};
array.forEach(function (val, idx) {
hash[val] = true;
});
return hash;
}
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatPrimitiveNoColor(ctx, value) {
var stylize = ctx.stylize;
ctx.stylize = stylizeNoColor;
var str = formatPrimitive(ctx, value);
ctx.stylize = stylize;
return str;
}
function isArray(ar) {
return Array.isArray(ar);
}
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || {value: value[key]};
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\'")
.replace(/\"/g, '"')
.replace(/(^"|"$)/g, "'")
.replace(/\\/g, '\');
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function (key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function reduceToSingleString(output, base, braces) {
var length = output.reduce(function (prev, cur) {
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// This could be a boxed primitive (new String(), etc.), check valueOf()
// NOTE: Avoid calling `valueOf` on `Date` instance because it will return
// a number which, when object has some additional user-stored `keys`,
// will be printed out.
var formatted;
var raw = value;
try {
// the .valueOf() call can fail for a multitude of reasons
if (!isDate(value))
raw = value.valueOf();
} catch (e) {
// ignore...
}
if (isString(raw)) {
// for boxed Strings, we have to remove the 0-n indexed entries,
// since they just noisey up the output and are redundant
keys = keys.filter(function (key) {
return !(key >= 0 && key < raw.length);
});
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
// now check the `raw` value to handle boxed primitives
if (isString(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[String: ' + formatted + ']', 'string');
}
if (isNumber(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[Number: ' + formatted + ']', 'number');
}
if (isBoolean(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[Boolean: ' + formatted + ']', 'boolean');
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
// Make boxed primitive Strings look like such
if (isString(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[String: ' + formatted + ']';
}
// Make boxed primitive Numbers look like such
if (isNumber(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[Number: ' + formatted + ']';
}
// Make boxed primitive Booleans look like such
if (isBoolean(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[Boolean: ' + formatted + ']';
}
if (keys.length === 0 && (!array || value.length === 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function (key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold': [1, 22],
'italic': [3, 23],
'underline': [4, 24],
'inverse': [7, 27],
'white': [37, 39],
'grey': [90, 39],
'black': [30, 39],
'blue': [34, 39],
'cyan': [36, 39],
'green': [32, 39],
'magenta': [35, 39],
'red': [31, 39],
'yellow': [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'symbol': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
var formatRegExp = /%[sdj%]/g;
exports.format = function (f) {
if (!isString(f)) {
var objects = [];
for (var j = 0; j < arguments.length; j++) {
objects.push(inspect(arguments[j]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function (x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s':
return String(args[i++]);
case '%d':
return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
собранный от:https://github.com/joyent/node/blob/master/lib/util.js
существует" sprintf " для JavaScript, который вы можете найти вhttp://www.webtoolkit.info/javascript-sprintf.html.
у меня есть немного более длинный форматтер для JavaScript здесь...
вы можете сделать форматирование несколькими способами:
String.format(input, args0, arg1, ...)
String.format(input, obj)
"literal".format(arg0, arg1, ...)
"literal".format(obj)
кроме того, если у вас есть, скажем, ObjectBase.прототип.формат (например, с DateJS) будет использоваться.
примеры...
var input = "numbered args ({0}-{1}-{2}-{3})";
console.log(String.format(input, "first", 2, new Date()));
//Outputs "numbered args (first-2-Thu May 31 2012...Time)-{3})"
console.log(input.format("first", 2, new Date()));
//Outputs "numbered args(first-2-Thu May 31 2012...Time)-{3})"
console.log(input.format(
"object properties ({first}-{second}-{third:yyyy-MM-dd}-{fourth})"
,{
'first':'first'
,'second':2
,'third':new Date() //assumes Date.prototype.format method
}
));
//Outputs "object properties (first-2-2012-05-31-{3})"
я тоже присвоить .asFormat и есть обнаружение на месте на случай, если уже есть строка.формат (например, С MS Ajax Toolkit (я ненавижу эту библиотеку).
на всякий случай, если кому-то нужна функция для предотвращения загрязнения глобальной области, вот функция, которая делает то же самое:
function _format (str, arr) {
return str.replace(/{(\d+)}/g, function (match, number) {
return typeof arr[number] != 'undefined' ? arr[number] : match;
});
};
для базового форматирования:
var template = jQuery.validator.format("{0} is not a valid value");
var result = template("abc");
Я не видел 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;
});
};
Я не вижу pyformat в списке, поэтому я решил бросить его:
console.log(pyformat( 'The {} {} jumped over the {}'
, ['brown' ,'fox' ,'foobar']
))
console.log(pyformat('The {0} {1} jumped over the {1}'
, ['brown' ,'fox' ,'foobar']
))
console.log(pyformat('The {color} {animal} jumped over the {thing}'
, [] ,{color: 'brown' ,animal: 'fox' ,thing: 'foobaz'}
))
/**
* Format string by replacing placeholders with value from element with
* corresponsing index in `replacementArray`.
* Replaces are made simultaneously, so that replacement values like
* '{1}' will not mess up the function.
*
* Example 1:
* ('{2} {1} {0}', ['three', 'two' ,'one']) -> 'one two three'
*
* Example 2:
* ('{0}{1}', ['{1}', '{0}']) -> '{1}{0}'
*/
function stringFormat(formatString, replacementArray) {
return formatString.replace(
/\{(\d+)\}/g, // Matches placeholders, e.g. '{1}'
function formatStringReplacer(match, placeholderIndex) {
// Convert String to Number
placeholderIndex = Number(placeholderIndex);
// Make sure that index is within replacement array bounds
if (placeholderIndex < 0 ||
placeholderIndex > replacementArray.length - 1
) {
return placeholderIndex;
}
// Replace placeholder with value from replacement array
return replacementArray[placeholderIndex];
}
);
}