相当于 printf / string 的 JavaScript。 格式

I'm looking for a good JavaScript equivalent of the C/PHP printf() or for C#/Java programmers, String.Format() (IFormatProvider for .NET).

My basic requirement is a thousand separator format for numbers for now, but something that handles lots of combinations (including dates) would be good.

I realize Microsoft's Ajax library provides a version of String.Format(), but we don't want the entire overhead of that framework.

转载于:https://stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format

csdnceshi71
Memor.の var search = [$scope.dog, "1"]; var url = vsprintf("earth/Services/dogSearch.svc/FindMe/%s/%s", search); ***For node, you can get your module by "npm install sprintf-js"
4 年多之前 回复
csdnceshi63
elliott.david I wrote a cheap one that uses C-like printf syntax.
4 年多之前 回复
csdnceshi60
℡Wang Yan Aside all the great answers below, you may want to take a look at this one: stackoverflow.com/a/2648463/1712065 which IMO, is the most efficient solution to this problem.
5 年多之前 回复

30个回答

Edit: From ES6 on you could use template strings:

let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!

See Kim's answer below for details.

Original answer:

Try sprintf() for JavaScript.


Update    Ok, if you really want to do a simple format method on your own, don’t do the replacements successively but do them simultaneously.

Because most of the other proposals that are mentioned fail when a replace string of previous replacement does also contain a format sequence like this:

"{0}{1}".format("{1}", "{0}")

Normally you would expect the output to be {1}{0} but the actual output is {1}{1}. So do a simultaneously replacement instead like in fearphage’s suggestion.

weixin_41568196
撒拉嘿哟木头 This shouldn't be accepted answer anymore. As of ES6 this is built into the javascript language (both in browsers and NodeJS). See @Kim 's answer below.
2 年多之前 回复
csdnceshi79
python小菜 I think the best is _.template function from lodash or underscore.
大约 4 年之前 回复
weixin_41568131
10.24 fearphage's suggestion now handles this test correctly.
接近 5 年之前 回复
csdnceshi80
胖鸭 I wrote a near-perfect replica of PHP's sprintf function for JavaScript, please enjoy: github.com/Alhadis/Snippets/blob/master/js/str-sprintf.js ... please bear in mind it DOES extend the String prototype (e.g., invoke it by "%f".sprintf(0.5), etc). It has zero external dependencies and is pretty damn fast too. Only discrepancies from PHP's implementation would be more lenient error handling. :-)
5 年多之前 回复
csdnceshi54
hurriedly% sprintf is great
接近 6 年之前 回复
csdnceshi64
游.程 A simple perf test, its more elegant to use ''.format but it has poor performance; use when necessary. jsperf.com/string-format-mjames
大约 6 年之前 回复
csdnceshi71
Memor.の the link is fine and goes through.
6 年多之前 回复
csdnceshi78
程序go right, just saying this answer is dead, and the link has decayed. It needs to be totally purged.
6 年多之前 回复
csdnceshi52
妄徒之命 you are right. At the time I wrote the comment the repository of sprintf() for JavaScript was not available. underscore.string has more features aside from sprintf which is based on sprintf() for JavaScript implementation. Other than that the library is an entirely different project.
6 年多之前 回复
csdnceshi78
程序go that seems to be something massively different.
6 年多之前 回复
csdnceshi57
perhaps? If only some simple number-to-string conversion is desired, num.toFixed() method might be enough!
接近 8 年之前 回复
csdnceshi52
妄徒之命 It's been moved again: epeli.github.com/underscore.string
8 年多之前 回复

Building on the previously suggested solutions:

// 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")

outputs

ASP is dead, but ASP.NET is alive! ASP {2}


If you prefer not to modify String's prototype:

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
      ;
    });
  };
}

Gives you the much more familiar:

String.format('{0} is dead, but {1} is alive! {0} {2}', 'ASP', 'ASP.NET');

with the same result:

ASP is dead, but ASP.NET is alive! ASP {2}

csdnceshi68
local-host The most recent version of chrome is not going through this code so whenever i try to do format i'm getting format is not a function, So i warped the code inside a function and i'm calling it before calling format!
接近 3 年之前 回复
csdnceshi52
妄徒之命 What If want something like in printf would do 4 -> "02d%" // produce 04?
接近 3 年之前 回复
csdnceshi57
perhaps? I really really wish I'd know you could pass a closure to replace sooner... Oh the time and lines of code I would have saved. This is an absolutely superb solution. thank you.
大约 3 年之前 回复
csdnceshi64
游.程 : Probably a silly question, but shouldn't args be inaccessible within the scope of the anonymous function being passed to String.replace()? Would an arrow function not be required instead?
大约 3 年之前 回复
csdnceshi60
℡Wang Yan Thanks for a great solution. I would add that for readability it might be worth using \w+ instead of \d+, and args = arguments[0]. This way you can have .format({'count': count, 'page': page, etc.}).
4 年多之前 回复
weixin_41568131
10.24 Dont't use this solution in performance oriented code blocks. It is terribly slow. jsperf.com/string-format-vs-string-concatenation
4 年多之前 回复
csdnceshi55
~Onlooker this version works with objects too: function format(str, args) { if (arguments.length > 2) args = Array.prototype.slice.call(arguments, 1); if (typeof args !== 'object') args = [ args ]; return str.replace(/{(.*?)}/g, function(match, item) { return typeof args[item] != 'undefined' ? args[item] : match; }); };
接近 5 年之前 回复
csdnceshi72
谁还没个明天 yes, that was a failure to read on my part. Consider my previous comment withdrawn.
5 年多之前 回复
csdnceshi58
Didn"t forge Your suggestion has a few caveats which I addressed 3 comments before yours. Thank you for the suggestion just the same.
5 年多之前 回复
csdnceshi72
谁还没个明天 You can shorten this a bit more by replacing the inner-most return expression with: return args[number] || match;
5 年多之前 回复
csdnceshi58
Didn"t forge Those are both valid suggestions for a much more strict environment. I won't be incorporating those, but I appreciate the suggestion.
5 年多之前 回复
csdnceshi75
衫裤跑路 I really like this and used it, but changed the If statement conditional check to be strict if (typeof String.prototype.format === "undefined") {, it is a personal preference. I also escaped the curly braces return this.replace(/\{(\d+)\}/g, function (match, number) {
5 年多之前 回复
csdnceshi58
Didn"t forge You can change the internal check to be less specific. Replace typeof args[number] != 'undefined' with args[number] != null. This will match both null and undefined values. If you never planned to pass in falsey values (0, empty string, boolean false, etc) you could remove ternary altogether and make it return args[number] || match.
接近 6 年之前 回复
csdnceshi65
larry*wei I know this is old, but I just got to it. Love this function! Thanks! However, I just ran into a problem where is a replacement value is null, it will put the word null as the value. Is this intended behavior? If not, can it be fixed/modified?
接近 6 年之前 回复
csdnceshi69
YaoRaoLov Note that String.format("{{0}}", "a") will give you "{a}" instead of "{0}", as the .NET version would. Tested several codes here and found one that works way down the list.
6 年多之前 回复
csdnceshi73
喵-见缝插针 The (!String.prototype.format) check is a bad idea unless dealing with polyfills, since it means that newer browsers can come along and break your website with an incompatible format method. I suggest removing it.
6 年多之前 回复
csdnceshi76
斗士狗 - Please do not repeatedly override the formatting of this answer against the will of the person who left it. I'm locking this for the next day, and if you wish to explain why you are doing this, please do so on Meta.
6 年多之前 回复
csdnceshi58
Didn"t forge Your code reformat invalidates the answer. It changes the output of the code. Please test your code before applying edits. Thank you.
6 年多之前 回复
csdnceshi80
胖鸭 Of course, a better example would be String.format('{{0}} was replaced with {0}', replcmnt);.
6 年多之前 回复
csdnceshi80
胖鸭 How about something like String.format('function() {{ {0} }}', fnBody);? Currently, the result would still have the double braces, but what if I want to replace those with a single one? That would be more concise with the .NET version. Really like your solution though! Nice and small! :)
6 年多之前 回复
weixin_41568126
乱世@小熊 More benchmarks, building on what @RandomEngy furnished, and snippets from other answers to this question: jsperf.com/stringformat/6
接近 7 年之前 回复
weixin_41568174
from.. I think this is better than sprintf() for JS because it does basically the same thing and it is very small.
大约 7 年之前 回复
weixin_41568196
撒拉嘿哟木头 /\{(\d+)\}/g
7 年多之前 回复
weixin_41568110
七度&光 Is there a way to make JSHint happy with the regex? "JSHint: Unescaped '{'."
7 年多之前 回复
csdnceshi58
Didn"t forge Your proposed solution suffers from the same things as some of the others here. '{0}{1}'.format('{1}', '{0}') should return {1}{0}. Also yours seems to only be faster in Firefox.
7 年多之前 回复
csdnceshi74
7*4 Oh my bad, it's only really slow in a WinJS app. Here's a jsperf of it: jsperf.com/stringformat .
7 年多之前 回复
csdnceshi58
Didn"t forge Thank you. Can you link to your test case please?
7 年多之前 回复
weixin_41568184
叼花硬汉 Nice! This even handles the tough example "{0}{1}".format("{1}", "{0}").
7 年多之前 回复
csdnceshi58
Didn"t forge That slightly and subtly changes the outcome. Imagine 'foo {0}'.format(fnWithNoReturnValue()). It would currently return foo {0}. With your changes, it would return foo undefined.
7 年多之前 回复
csdnceshi66
必承其重 | 欲带皇冠 Great little function. The typeof check could be replaced with return number in args to make it even shorter.
7 年多之前 回复
weixin_41568134
MAO-EYE If you have multiple strings appended to each other (with the +-operator), be sure to put the complete String in parentheses: ("asd {0}"+"fas {1}").format("first", "second"); Otherwise, the function will only be applied to the last string that was appended.
大约 8 年之前 回复
csdnceshi63
elliott.david in the else statement of the shorthand if, why not just do "match" instead of "'{' + number + '}'". match should equal that string.
9 年多之前 回复
csdnceshi56
lrony* the || trick doesn't work if args[number] is 0. Should do an explicit if() to see if (args[number] === undefined).
9 年多之前 回复

It's funny because Stack Overflow actually has their own formatting function for the String prototype called formatUnicorn. Try it! Go into the console and type something like:

"Hello, {name}, are you feeling {adjective}?".formatUnicorn({name:"Gabriel", adjective: "OK"});

Firebug

You get this output:

Hello, Gabriel, are you feeling OK?

You can use objects, arrays, and strings as arguments! I got its code and reworked it to produce a new version of 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;
};

Note the clever Array.prototype.slice.call(arguments) call -- that means if you throw in arguments that are strings or numbers, not a single JSON-style object, you get C#'s String.Format behavior almost exactly.

"a{0}bcd{1}ef".formatUnicorn("foo", "bar"); // yields "aFOObcdBARef"

That's because Array's slice will force whatever's in arguments into an Array, whether it was originally or not, and the key will be the index (0, 1, 2...) of each array element coerced into a string (eg, "0", so "\\{0\\}" for your first regexp pattern).

Neat.

csdnceshi75
衫裤跑路 I can't believe you Little Bobby Tabled me. ;) If you're running text processed by client-side JavaScript on your database server without any safety checks, heaven help us all. ;^) Look, there shouldn't be anything any user can send from a client (eg, Postman) that gets past your server's security. And you should assume anything dangerous that could be sent from a client will be. That is, if you require 100% safety from client-side JavaScript code which is always user editable, and you think this function could open a security risk, you're playing in the wrong game.
2 年多之前 回复
csdnceshi60
℡Wang Yan "If I had ever learnt, I should have been a great proficient." - Lady Catherine de Bourgh. :-)
接近 3 年之前 回复
csdnceshi58
Didn"t forge yes, stuff fed to {name} is typically user data. I do not know whether SO is vulnerable, but I do know they use a buggy function. (sadly, I came here looking for available options for string interpolation in JS and am thus unable to provide an improvement, but rest assured I would have had I been more literate in that language)
3 年多之前 回复
csdnceshi75
衫裤跑路 By assuming "user data", you've made this a much different conversation, one I don't see implied by the OP or this answer. As you're presenting, you might as well throw out String.replace too. ;^) I've given code that stops circular refs. Do you think SO is vulnerable somehow for using formatUnicorn? Or I'm missing your point entirely -- maybe you could submit an answer that improves on this one? (Btw, 99.44% (sorry for 98 typo earlier) is just a colloquialism)
3 年多之前 回复
csdnceshi58
Didn"t forge “a little hyperbolic”? Code that is fooled into interpreting user data as format strings is an entire category of vulnerabilities. 98.44% is beyond mediocre.
3 年多之前 回复
csdnceshi75
衫裤跑路 Um, "Hello, blah OK blah, are you feeling OK?", natch. "Awfully" seems a little hyperbolic. If you wanted to code to ignore { in replacement values, you could easily or even make two passes if you want the more troublesome adjective = "blah {name} blah" to execute -- but boy, it does 98.44% of the job well as is, I believe.
3 年多之前 回复
csdnceshi58
Didn"t forge This seems awfully fragile, to be honest. What happens for instance if name is "blah {adjective} blah"?
接近 4 年之前 回复
csdnceshi65
larry*wei This method is much better than something like sprintf, since the named placeholders allow ordering. This is important if you outsource the initial string e. g. for localization. Imagine you have something like sprintf("Hello %s %s", ..., ...). In one language you want to place the forename first and then the surname, but in other language the surname first. The missing formatting is a disadvantage but one can still format the value in the params.
接近 4 年之前 回复
csdnceshi76
斗士狗 This would be cooler if you could just put javascript expressions inside the curly braces and dispense with the names. c# 6.0 has this now.
大约 4 年之前 回复
csdnceshi62
csdnceshi62 This behaves weird if args[arg] contains $1, $' etc. The solution is to replace args[arg] with function() { return args[arg]; }.
4 年多之前 回复
csdnceshi79
python小菜 Yes, you're right, sorry.
大约 5 年之前 回复
weixin_41568184
叼花硬汉 here is a demo jsbin.com/keluvukuka/edit?html,console,output
大约 5 年之前 回复
weixin_41568184
叼花硬汉 but the code for (arg in args) will define a global variable named arg. If you're not using var arg at the first line, then you should use for(var arg in args) to avoid defining the global variable.
大约 5 年之前 回复
csdnceshi79
python小菜 there is no typo. He are just reusing the same variable to store the typeof and then, in the next line, the arguments.
大约 5 年之前 回复
weixin_41568184
叼花硬汉 I think there is a typo: var args = typeof arguments[0] should be var arg = typeof arguments[0]
5 年多之前 回复
csdnceshi63
elliott.david The regex allows the global flag (g), which can replace the same key more than once. In the example above, you could use {name} multiple times in the same sentence and have them all replaced.
6 年多之前 回复
csdnceshi53
Lotus@ Anyone understand why they're using a regex for the replace instead of just a string?
6 年多之前 回复
weixin_41568127
?yb? It's pretty cool to answer a question on stackoverflow with code from stackoverflow, +1
接近 7 年之前 回复

I use this simple function:

String.prototype.format = function() {
    var formatted = this;
    for( var arg in arguments ) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};

That's very similar to string.format:

"{0} is dead, but {1} is alive!".format("ASP", "ASP.NET")
weixin_41568183
零零乙 The function is unsafe as it sometimes interprets {n}s within the strings passed to it: '{0}'.format('you should only see this {1}', 'you should not see this')
大约 2 年之前 回复
csdnceshi69
YaoRaoLov formatted.replace(new RegExp("\\{" + arg + "\\}", "g"), arguments[arg]) allows you to repeat indexes in case you need to duplicate values in the string.
6 年多之前 回复
csdnceshi57
perhaps? The variable arg is global. You need to do this instead: for (var arg in arguments) {
接近 8 年之前 回复
weixin_41568134
MAO-EYE This fails if a previous replacement contains a format string as well: "{0} is dead, but {1} is alive!".format("{1}", "ASP.NET") === "ASP.NET is dead, but ASP.NET is alive!"
9 年多之前 回复
csdnceshi58
Didn"t forge For reference, for...in won't work in every browser as this code expects it to. It'll loop over all enumerable properties, which in some browsers will include arguments.length, and in others won't even include the arguments themselves at all. In any case, if Object.prototype is added to, any additions will probably be included in the bunch. The code should be using a standard for loop, rather than for...in.
9 年多之前 回复
csdnceshi54
hurriedly% I think the code is still not correct. The correct one one should be like Filipiz posted.
接近 10 年之前 回复
csdnceshi60
℡Wang Yan Ahh, but now I see he's adding the whole replacement to the string every time, you're right. user437231's answer is correct. For some reason I was thinking this.replace was only returning the replaced part...
接近 10 年之前 回复
csdnceshi60
℡Wang Yan It shouldn't be =, it should be +=, because arguments[arg] may not be a string. Because format is already a string outside the loop, + will concatenate the string, and arguments[arg] will automatically have .toString() called on it. If arguments[0] was 5 and arguments[1] was 7, then instead of "{1}{2}".format(5,7) returning 57, the first argument will yield 12 and the second one will throw an out of bounds exception.
接近 10 年之前 回复
csdnceshi67
bug^君 why +=?, should it formatted = this.replace("{" + arg + "}", arguments[arg]);
接近 10 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 What about "{{0}} use this next instead {0}"? Not really a String.Format, but it is small and nice function to use.
接近 10 年之前 回复

From ES6 on you could use template strings:

let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!

Be aware that template strings are surrounded by backticks ` instead of (single) quotes.

For further information:

https://developers.google.com/web/updates/2015/01/ES6-Template-Strings

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings

Note: Check the mozilla-site to find a list of supported browsers.

csdnceshi61
derek5. +1 for using the standard built in function which can be helpful in a lot of situations. here a list of polyfills for supporting older browsers
大约 3 年之前 回复
csdnceshi59
ℙℕℤℝ That works fine if your template function is defined on the same machine where it is executed. As far as I know, you can't pass a function as JSON, so storing template functions in a database doesn't work well.
3 年多之前 回复
csdnceshi60
℡Wang Yan this solution won't work for format string passed in variable (from server for example)
接近 4 年之前 回复
csdnceshi52
妄徒之命 Actually, I've since looked at the Mozilla link given in this answer and see that their example tagged template that returns a function isn't a bad way to do i18n-like string tables, where you can pass the returned function the parameters you want to put into the string. Granted, I don't know how that compares in memory size to simply strings you interpolate by replacing {0} markers.
4 年多之前 回复
csdnceshi72
谁还没个明天 there is no difference between using a template string or old style string concatenation, its sugar for the same thing. You would have to wrap an old style string generator in a simple function and the same thing works fine with string templates. const compile = (x, y) => I can call this template string whenever I want.. x=${x}, y=${y} ... compile(30, 20)
4 年多之前 回复
csdnceshi68
local-host You're right that they're not built to be assigned to a variable, which is a bit mind-warping, but it's easy enough to work with templated strings' instant-execution tendancies if you hide them in a function. See jsfiddle.net/zvcm70pa
4 年多之前 回复
csdnceshi52
妄徒之命 The problem with template strings is that they seem to be executed immediately, making their use as, say, an i18n-like string table completely worthless. I can't define the string early on, and supply the parameters to use later and/or repeatedly.
接近 5 年之前 回复

I use a small library called String.format for JavaScript which supports most of the format string capabilities (including format of numbers and dates), and uses the .NET syntax. The script itself is smaller than 4 kB, so it doesn't create much of overhead.

csdnceshi51
旧行李 You are right pasting it would be no better. I just got this comment for random review - and commented before disliking it. To me stackoverflow is better when providing explanations rather than ready made solutions (which the link is). I also do not want to encourage people to post or download black-box code.
6 年多之前 回复
csdnceshi72
谁还没个明天 the link is to a (minified) 4 kB javascript library. I don't believe pasting it into the answer is a good idea.
6 年多之前 回复
csdnceshi51
旧行李 While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
6 年多之前 回复
csdnceshi74
7*4 Often a downloadable archive that's an EXE is nothing more than a "self-extracting ZIP". Execute it, and it will unpack itself. This is quite convenient BUT because it looks so much like malware, the format is not used on the web all that often any more.
7 年多之前 回复
csdnceshi76
斗士狗 Not an exe any more, looks pretty excellent.
10 年多之前 回复
csdnceshi53
Lotus@ I took a look at that library and it looks really great. I was pissed off when I saw that the download was an EXE. What the heck is that about? Didn't download.
10 年多之前 回复

Number Formatting in JavaScript

I got to this question page hoping to find how to format numbers in JavaScript, without introducing yet another library. Here's what I've found:

Rounding floating-point numbers

The equivalent of sprintf("%.2f", num) in JavaScript seems to be num.toFixed(2), which formats num to 2 decimal places, with rounding (but see @ars265's comment about Math.round below).

(12.345).toFixed(2); // returns "12.35" (rounding!)
(12.3).toFixed(2); // returns "12.30" (zero padding)

Exponential form

The equivalent of sprintf("%.2e", num) is num.toExponential(2).

(33333).toExponential(2); // "3.33e+4"

Hexadecimal and other bases

To print numbers in base B, try num.toString(B). JavaScript supports automatic conversion to and from bases 2 through 36 (in addition, some browsers have limited support for base64 encoding).

(3735928559).toString(16); // to base 16: "deadbeef"
parseInt("deadbeef", 16); // from base 16: 3735928559

Reference Pages

Quick tutorial on JS number formatting

Mozilla reference page for toFixed() (with links to toPrecision(), toExponential(), toLocaleString(), ...)

csdnceshi60
℡Wang Yan Or (33333).toExponential(2)
大约 4 年之前 回复
csdnceshi63
elliott.david .. also works: 33333..toExponential(2);
7 年多之前 回复
csdnceshi70
笑故挽风 Just a side note if you're using an older browser, or supporting older browsers, some browsers implemented toFixed incorrectly, using Math.round in place of toFixed is a better solution.
7 年多之前 回复
csdnceshi50
三生石@ That would probably look better, true. But my goal there is just to point out the syntax error trap.
接近 8 年之前 回复
csdnceshi64
游.程 Wouldn't it just be better to enclose the number literal in parenthesis, instead of leaving a weird white space there?
接近 8 年之前 回复

jsxt, Zippo

This option fits better.

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;
};

With this option I can replace strings like these:

'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP');

With your code the second {0} wouldn't be replaced. ;)

csdnceshi79
python小菜 you don't declara a variable inside a for loop
接近 7 年之前 回复
csdnceshi64
游.程 jsxt is GPL-licensed unfortunately
8 年多之前 回复
csdnceshi60
℡Wang Yan gist.github.com/1049426 I updated your example with this approach. Numerous benefits including saving the native implementation if it exists, stringifying, etc. I tried removing regular expressions, but welp kind of needed for global replace. :-/
9 年多之前 回复
csdnceshi80
胖鸭 I like this, since it globally replaces the format tokens.
9 年多之前 回复

I'm surprised no one used reduce, this is a native concise and powerful JavaScript function.

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'));

< 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"

How it works:

reduce applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value.

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")
);

</div>
weixin_41568208
北城已荒凉 You'd have to implement replacement functions for each of printf's type specifiers and include logic for padding prefixes. Iterating over the format string in a sensible fashion seems to be the minor challenge here, imho. Neat solution if you only need string replacements, though.
2 年多之前 回复
csdnceshi74
7*4 No need for String.prototype.format in ES6: ((a,b,c)=>${a}, ${b} and ${c})(...['me', 'myself', 'I']) (note that this is a bit redundant to better fit in your example)
2 年多之前 回复
csdnceshi64
游.程 And here is another one using ES6, in one line: (...a) => {return a.reduce((p: string, c: any) => p.replace(/%s/, c));
2 年多之前 回复
csdnceshi59
ℙℕℤℝ Here's a version that uses this approach to create a simplified printf function: jsfiddle.net/11szrbx9
5 年多之前 回复

+1 Zippo with the exception that the function body needs to be as below or otherwise it appends the current string on every iteration:

String.prototype.format = function() {
    var formatted = this;
    for (var arg in arguments) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};
csdnceshi61
derek5. For reference, for...in won't work in every browser as this code expects it to. It'll loop over all enumerable properties, which in some browsers will include arguments.length, and in others won't even include the arguments themselves at all. In any case, if Object.prototype is added to, any additions will probably be included in the bunch. The code should be using a standard for loop, rather than for...in.
9 年多之前 回复
csdnceshi51
旧行李 It does not replace the second character 'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP'); the result becomes The ASP is dead. Don't code {0}. Code PHP that is open source!. One more thing for(arg in arguments) does not work in IE. i replaced with for (arg = 0; arg <arguments.length; arg++)
9 年多之前 回复
csdnceshi76
斗士狗 Yeah I didn't post the code correctly, thanks for fixing :)
接近 10 年之前 回复
csdnceshi62
csdnceshi62 It didn't work on Firefox. The debugger show arg as undefined.
接近 10 年之前 回复
共30条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐