我正在寻找一个与C/PHP printf()或C#/Java程序员String.Format()(IFormatProvider for.NET)相当的JavaScript。

目前,我的基本要求是数字的千位分隔符格式,但处理大量组合(包括日期)的格式会很好。

我意识到Microsoft的Ajax库提供了String.Format()的一个版本,但我们不希望该框架的全部开销。


当前回答

旧答案的修改代码https://stackoverflow.com/a/18234317/19531844效率更高(没有较慢的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

其他回答

用于jQuery.ajax()成功函数。只传递一个参数,并用该对象的财产替换字符串作为{propertyName}:

String.prototype.format = function () {
    var formatted = this;
    for (var prop in arguments[0]) {
        var regexp = new RegExp('\\{' + prop + '\\}', 'gi');
        formatted = formatted.replace(regexp, arguments[0][prop]);
    }
    return formatted;
};

例子:

var userInfo = ("Email: {Email} - Phone: {Phone}").format({ Email: "someone@somewhere.com", Phone: "123-123-1234" });

JavaScript中的数字格式

我来到这个问题页面,希望找到如何在JavaScript中格式化数字,而不引入另一个库。以下是我的发现:

舍入浮点数

JavaScript中sprintf(“%.2f”,num)的等价物似乎是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)的等效值为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数字格式快速教程

toFixed()的Mozilla参考页(带有指向Precision()、toExponential()、toLocaleString()等的链接)

除了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 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!");

对于Node.js用户,util.format具有类似printf的功能:

util.format("%s world", "Hello")