JavaScript tương đương với printf / String.Format


1970

Tôi đang tìm kiếm một JavaScript tương đương tốt với C / PHP printf()hoặc cho các lập trình viên C # / Java, String.Format()( IFormatProviderđối với .NET).

Yêu cầu cơ bản của tôi là một định dạng dấu phân cách cho các số hiện tại, nhưng một số thứ xử lý nhiều kết hợp (bao gồm cả ngày) sẽ tốt.

Tôi nhận thấy thư viện Ajax của Microsoft cung cấp một phiên bản String.Format(), nhưng chúng tôi không muốn toàn bộ chi phí của khung đó.


2
Bên cạnh tất cả các câu trả lời tuyệt vời dưới đây, bạn có thể muốn xem qua câu trả lời này: stackoverflow.com/a/2648463/1712065 mà IMO, là giải pháp hiệu quả nhất cho vấn đề này.
Annie

1
Tôi đã viết một cái giá rẻ sử dụng cú pháp printf giống như C.
Braden hay nhất

tìm kiếm var = [$ scope.dog, "1"]; var url = vsprintf (" trái đất / Dịch vụ / dogSearch.svc / FindMe /% s /% s ", tìm kiếm); *** Đối với nút, bạn có thể nhận mô-đun của mình bằng cách "npm install sprintf-js"
Jenna Leaf

Tôi cũng đã viết một chức năng đơn giản để đạt được điều này; stackoverflow.com/a/54345052/5927126
AnandShanbhag

Câu trả lời:


1109

Từ ES6 trở đi, bạn có thể sử dụng các chuỗi mẫu:

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

Xem câu trả lời của Kim dưới đây để biết chi tiết.


Nếu không thì:

Hãy thử sprintf () cho JavaScript .


Nếu bạn thực sự muốn tự mình thực hiện một phương pháp định dạng đơn giản, đừng thực hiện thay thế liên tiếp mà hãy thực hiện chúng đồng thời.

Bởi vì hầu hết các đề xuất khác được đề cập đều thất bại khi chuỗi thay thế thay thế trước đó cũng chứa một chuỗi định dạng như thế này:

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

Thông thường bạn sẽ mong đợi đầu ra là {1}{0}nhưng đầu ra thực tế là {1}{1}. Vì vậy, thay thế đồng thời thay vì như trong đề xuất của sợ hãi .


16
Nếu chỉ cần một số chuyển đổi số thành chuỗi đơn giản, num.toFixed()phương thức có thể là đủ!
heltonbiker

@MaksymilianMajer dường như là một cái gì đó khác biệt lớn.
Evan Carroll

@EvanCarroll bạn nói đúng. Tại thời điểm tôi viết bình luận, kho lưu trữ sprintf() for JavaScriptkhông có sẵn. underscore.stringcó nhiều tính năng hơn ngoài sprintf dựa trên sprintf() for JavaScriptviệc thực hiện. Khác hơn là thư viện là một dự án hoàn toàn khác.
Maksymilian Majer

@MaksymilianMajer đúng, chỉ cần nói câu trả lời này là chết, và liên kết đã bị phân rã. Nó cần phải được thanh trừng hoàn toàn.
Evan Carroll

2
Điều này không nên được chấp nhận câu trả lời nữa. Kể từ ES6, nó được tích hợp vào ngôn ngữ javascript (cả trong trình duyệt và NodeJS). Xem câu trả lời của @Kim bên dưới.
Ryan Shillington

1390

Dựa trên các giải pháp được đề xuất trước đây:

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

đầu ra

ASP đã chết, nhưng ASP.NET vẫn còn sống! ASP {2}


Nếu bạn không muốn sửa đổi Stringnguyên mẫu của:

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

Cung cấp cho bạn nhiều quen thuộc hơn:

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

với kết quả tương tự:

ASP đã chết, nhưng ASP.NET vẫn còn sống! ASP {2}


12
| | lừa không hoạt động nếu args [số] bằng 0. Nên làm rõ if () để xem if (args [number] === không xác định).
fserb

4
trong câu lệnh khác của tốc ký nếu, tại sao không chỉ làm "khớp" thay vì "'{' + số + '}'". phù hợp nên bằng chuỗi đó.
mikeycgto

4
Nếu bạn có nhiều chuỗi được nối với nhau (với +-operator), hãy đảm bảo đặt Chuỗi hoàn chỉnh trong ngoặc đơn: ("asd {0}"+"fas {1}").format("first", "second");Nếu không, hàm sẽ chỉ được áp dụng cho chuỗi cuối cùng được nối.
Lukas Knuth

3
Điều đó thay đổi một chút và tinh tế kết quả. Hãy tưởng tượng 'foo {0}'.format(fnWithNoReturnValue()). Nó hiện sẽ trở lại foo {0}. Với những thay đổi của bạn, nó sẽ trở lại foo undefined.
sợ hãi

2
@avenmore: / \ {(\ d +) \} / g
Hozuki

491

Thật buồn cười vì Stack Overflow thực sự có chức năng định dạng riêng cho Stringnguyên mẫu được gọi formatUnicorn. Thử nó! Đi vào bảng điều khiển và gõ một cái gì đó như:

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

Bọ lửa

Bạn nhận được đầu ra này:

Hello, Gabriel, are you feeling OK?

Bạn có thể sử dụng các đối tượng, mảng và chuỗi làm đối số! Tôi đã nhận được mã của nó và làm lại nó để tạo ra một phiên bản mới của 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;
};

Lưu ý Array.prototype.slice.call(arguments)cuộc gọi thông minh - điều đó có nghĩa là nếu bạn đưa ra các đối số là chuỗi hoặc số, không phải là một đối tượng kiểu JSON, bạn sẽ có được String.Formathành vi của C # gần như chính xác.

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

Đó là vì Array's slicesẽ buộc bất cứ điều gì trong argumentsthành Array, cho dù đó là ban đầu hay không, và keysẽ là chỉ số (0, 1, 2 ...) của mỗi phần tử mảng ép buộc vào một chuỗi (ví dụ, '0', do đó "\\{0\\}"cho mẫu regrec đầu tiên của bạn).

Khéo léo.


402
Thật tuyệt khi trả lời một câu hỏi về stackoverflow với mã từ stackoverflow, +1
Sneakyness

5
@JamesManning Regex cho phép cờ toàn cầu ( g), có thể thay thế cùng một khóa nhiều lần. Trong ví dụ trên, bạn có thể sử dụng {name}nhiều lần trong cùng một câu và thay thế tất cả chúng.
KrekkieD

3
Điều này có vẻ hết sức mong manh, thành thật mà nói. Điều gì xảy ra nếu name"blah {adjective} blah"?
sam hocevar

5
@ruffin Cảnh một chút cường điệu? Mã bị lừa để diễn giải dữ liệu người dùng dưới dạng chuỗi định dạng là toàn bộ danh mục các lỗ hổng . 98,44% là vượt quá tầm thường .
sam hocevar

3
@samhocevar Tôi không thể tin bạn Little Bobby Tabled tôi. ;) Nếu bạn đang chạy văn bản được xử lý bởi JavaScript phía máy khách trên máy chủ cơ sở dữ liệu của bạn mà không có bất kỳ kiểm tra an toàn nào, trời sẽ giúp tất cả chúng ta. ; ^) Hãy nhìn xem, không nên có bất cứ điều gì mà bất kỳ người dùng nào có thể gửi từ khách hàng (ví dụ: Người đưa thư) vượt qua bảo mật máy chủ của bạn. Và bạn nên cho rằng bất cứ điều gì nguy hiểm có thể được gửi từ khách hàng sẽ là. Nghĩa là, nếu bạn yêu cầu 100% an toàn từ phía khách hàng mã JavaScript mà là luôn luôn sử dụng có thể chỉnh sửa, và bạn nghĩ rằng chức năng này có thể mở ra một nguy cơ bảo mật, bạn đang chơi trong game sai.
ruffin

325

Định dạng số trong JavaScript

Tôi đã đến trang câu hỏi này với hy vọng tìm cách định dạng số trong JavaScript mà không cần giới thiệu một thư viện khác. Đây là những gì tôi đã tìm thấy:

Làm tròn số dấu phẩy động

Tương đương với sprintf("%.2f", num)JavaScript dường như là num.toFixed(2)định dạng numđến 2 chữ số thập phân, với làm tròn (nhưng xem nhận xét của @ ars265 Math.roundbên dưới).

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

Dạng hàm mũ

Tương đương sprintf("%.2e", num)num.toExponential(2).

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

Hệ thập lục phân và các căn cứ khác

Để in số trong cơ sở B, hãy thử num.toString(B). JavaScript hỗ trợ chuyển đổi tự động sang và từ cơ sở 2 đến 36 (ngoài ra, một số trình duyệt có hỗ trợ hạn chế cho mã hóa base64 ).

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

Trang tham khảo

Hướng dẫn nhanh về định dạng số JS

Trang tham chiếu Mozilla cho toFixed () (có liên kết đến toPrecision (), toExponential (), toLocaleString (), ...)


23
Sẽ không tốt hơn nếu bao gồm chữ số trong ngoặc đơn, thay vì để lại một khoảng trắng kỳ lạ ở đó?
rmobis

7
Điều đó có thể sẽ tốt hơn, đúng. Nhưng mục tiêu của tôi chỉ là chỉ ra bẫy lỗi cú pháp.
rescdsk

4
Chỉ là một lưu ý phụ nếu bạn đang sử dụng trình duyệt cũ hơn hoặc hỗ trợ các trình duyệt cũ hơn, một số trình duyệt được triển khai không chính xác, sử dụng Math.round thay cho toFixed là một giải pháp tốt hơn.
ars265

7
@Raphael_ và @rescdsk: ..cũng hoạt động:33333..toExponential(2);
Peter Jaric

Hoặc (33333) .toExponential (2)
Jonathan

245

Từ ES6 trở đi, bạn có thể sử dụng các chuỗi mẫu :

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

Xin lưu ý rằng các chuỗi mẫu được bao quanh bởi các dấu ngoặc kép `thay vì dấu ngoặc đơn (đơn).

Để biết thêm thông tin:

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

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

Lưu ý: Kiểm tra trang web mozilla để tìm danh sách các trình duyệt được hỗ trợ.


61
Vấn đề với các chuỗi mẫu là dường như chúng được thực thi ngay lập tức, khiến cho việc sử dụng chúng như một bảng chuỗi giống như i18n hoàn toàn không có giá trị. Tôi không thể xác định sớm chuỗi và cung cấp các tham số để sử dụng sau và / hoặc lặp lại.
Tustin2121

4
@ Tustin2121 Bạn có quyền rằng chúng không được xây dựng để được gán cho một biến, điều này hơi khó hiểu, nhưng nó đủ dễ để làm việc với các xu hướng thực thi tức thời của chuỗi templated nếu bạn ẩn chúng trong một hàm. Xem jsfiddle.net/zvcm70pa
inanutshellus

13
@ Tustin2121 không có sự khác biệt giữa việc sử dụng chuỗi mẫu hoặc nối chuỗi kiểu cũ, đường của nó cho cùng một thứ. Bạn sẽ phải bọc một trình tạo chuỗi kiểu cũ trong một hàm đơn giản và điều tương tự cũng hoạt động tốt với các mẫu chuỗi. const compile = (x, y) => `I can call this template string whenever I want.. x=${x}, y=${y}`...compile(30, 20)
cchamberlain

4
giải pháp này sẽ không hoạt động đối với chuỗi định dạng được truyền trong biến (ví dụ từ máy chủ)
user993954

1
@inanutshellus Điều đó hoạt động tốt nếu chức năng mẫu của bạn được xác định trên cùng một máy nơi nó được thực thi. Theo tôi biết, bạn không thể truyền một hàm như JSON, vì vậy việc lưu trữ các hàm mẫu trong cơ sở dữ liệu không hoạt động tốt.
styfle

171

jsxt, Zippo

Tùy chọn này phù hợp hơn.

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

Với tùy chọn này, tôi có thể thay thế các chuỗi như sau:

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

Với mã của bạn, {0} thứ hai sẽ không được thay thế. ;)


3
gist.github.com/1049426 Tôi đã cập nhật ví dụ của bạn với phương pháp này. Nhiều lợi ích bao gồm tiết kiệm thực hiện riêng nếu nó tồn tại, xâu chuỗi, v.v. Tôi đã thử loại bỏ các biểu thức thông thường, nhưng loại welp cần thiết để thay thế toàn cầu. : - /
tbranyen

6
jsxt không may được cấp phép GPL
AndiDog

109

Tôi sử dụng chức năng đơn giản này:

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

Điều đó rất giống với string.format:

"{0} is dead, but {1} is alive!".format("ASP", "ASP.NET")

1
tại sao +=?, nênformatted = this.replace("{" + arg + "}", arguments[arg]);
guilin

2
Tôi nghĩ rằng mã vẫn không đúng. Một trong những chính xác nên được như Filipiz đăng.
wenqiang

3
Để tham khảo, for...insẽ không hoạt động trong mọi trình duyệt vì mã này mong đợi nó. Nó sẽ lặp trên tất cả các thuộc tính có thể đếm được, trong một số trình duyệt sẽ bao gồm arguments.lengthvà trong các trình duyệt khác thậm chí sẽ không bao gồm chính các đối số. Trong mọi trường hợp, nếu Object.prototypeđược thêm vào, bất kỳ bổ sung nào có thể sẽ được bao gồm trong bó. Mã nên được sử dụng một forvòng lặp tiêu chuẩn , chứ không phải for...in.
cHao

3
Điều này không thành công nếu thay thế trước đó cũng chứa một chuỗi định dạng:"{0} is dead, but {1} is alive!".format("{1}", "ASP.NET") === "ASP.NET is dead, but ASP.NET is alive!"
Gumbo

6
Các biến arglà toàn cầu. Bạn cần phải làm điều này thay vào đó:for (var arg in arguments) {
Pauan

68

Đối với người dùng Node.jsutil.format , có chức năng giống như printf:

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

1
Điều này không hỗ trợ% x kể từ Node v0.10.26
Max Krohn

Không hỗ trợ sửa đổi độ rộng và căn chỉnh (ví dụ %-20s %5.2f)
FGM

Tôi đã phải cuộn tất cả các trang xuống để xem câu trả lời hữu ích này.
Donato

53

Tôi ngạc nhiên không ai sử dụng reduce, đây là một hàm JavaScript mạnh mẽ và súc tích.

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"

Làm thế nào nó hoạt động:

giảm áp dụng một hàm chống lại bộ tích lũy và từng phần tử trong mảng (từ trái sang phải) để giảm nó thành một giá trị duy nhất.

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


4
Đây là phiên bản sử dụng phương pháp này để tạo ra một printfchức năng đơn giản : jsfiddle.net/11szrbx9
Dem Pilafian 20/07/2015

1
Và đây là một cái khác sử dụng ES6, trong một dòng:(...a) => {return a.reduce((p: string, c: any) => p.replace(/%s/, c));
dtasev

Không cần String.prototype.formattrong ES6: ((a,b,c)=>`${a}, ${b} and ${c}`)(...['me', 'myself', 'I'])(lưu ý rằng điều này hơi dư thừa để phù hợp hơn với ví dụ của bạn)
Tino

Bạn sẽ phải triển khai các chức năng thay thế cho từng printfchỉ định loại và bao gồm logic cho phần đệm tiền tố. Lặp lại chuỗi định dạng theo cách hợp lý dường như là thách thức nhỏ ở đây, imho. Giải pháp gọn gàng nếu bạn chỉ cần thay thế chuỗi, mặc dù.
sụp đổ

51

Đây là một triển khai tối thiểu của sprintf trong JavaScript: nó chỉ thực hiện "% s" và "% d", nhưng tôi đã để lại không gian cho nó được mở rộng. OP là vô dụng, nhưng những người khác vấp phải chủ đề này đến từ Google có thể được hưởng lợi từ nó.

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

Thí dụ:

alert(sprintf('Latitude: %s, Longitude: %s, Count: %d', 41.847, -87.661, 'two'));
// Expected output: Latitude: 41.847, Longitude: -87.661, Count: 0

Ngược lại với các giải pháp tương tự trong các lần trả lời trước, điều này thực hiện tất cả các thay thế trong một lần , vì vậy nó sẽ không thay thế các phần của các giá trị được thay thế trước đó.


31

Các lập trình viên JavaScript có thể sử dụng String.prototype.sprintf tại https://github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js . Dưới đây là ví dụ:

var d = new Date();
var dateStr = '%02d:%02d:%02d'.sprintf(
    d.getHours(), 
    d.getMinutes(), 
    d.getSeconds());

@JasonMorgan, tôi đã chia sẻ liên kết hoạt động trên GitHub. Xem câu trả lời chính xác.
jsxt

24

Thêm vào zippoxercâu trả lời, tôi sử dụng chức năng này:

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.

Tôi cũng có một phiên bản không phải nguyên mẫu mà tôi sử dụng thường xuyên hơn cho cú pháp giống như Java của nó:

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

Cập nhật ES 2015

Tất cả những thứ mới mẻ thú vị trong ES 2015 giúp việc này trở nên dễ dàng hơn rất nhiều:

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

Tôi hình dung rằng vì điều này, giống như những cái cũ hơn, không thực sự phân tích các chữ cái, nó cũng có thể chỉ sử dụng một mã thông báo duy nhất %%. Điều này có lợi ích là rõ ràng và không gây khó khăn khi sử dụng một %. Tuy nhiên, nếu bạn cần %%một số lý do, bạn sẽ cần phải thay thế nó bằng chính nó:

format("I love percentage signs! %%", "%%");
// "I love percentage signs! %%"

3
câu trả lời này là tuyệt vời cho một bản sao nhanh chóng dán vào một chức năng hiện có. Không yêu cầu không tải xuống, v.v.
Nick

@Nick yep, đó là ý tưởng :)
Braden Best

21

+1 Zippo với ngoại lệ là phần thân hàm cần phải như bên dưới hoặc nếu không, nó sẽ nối thêm chuỗi hiện tại vào mỗi lần lặp:

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

1
Nó không hoạt động trên Firefox. Trình gỡ lỗi hiển thị arg là không xác định.
xiao

Nó không thay thế nhân vật thứ hai 'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP'); mà kết quả trở thành The ASP is dead. Don't code {0}. Code PHP that is open source!. Một điều nữa for(arg in arguments)không hoạt động trong IE. tôi đã thay thế bằng for (arg = 0; arg <arguments.length; arg++)
samarjit samanta

2
Để tham khảo, for...insẽ không hoạt động trong mọi trình duyệt vì mã này mong đợi nó. Nó sẽ lặp trên tất cả các thuộc tính có thể đếm được, trong một số trình duyệt sẽ bao gồm arguments.lengthvà trong các trình duyệt khác thậm chí sẽ không bao gồm chính các đối số. Trong mọi trường hợp, nếu Object.prototypeđược thêm vào, bất kỳ bổ sung nào có thể sẽ được bao gồm trong bó. Mã nên được sử dụng một forvòng lặp tiêu chuẩn , chứ không phải for...in.
cHao

Bạn nên đề xuất chỉnh sửa câu trả lời thay vì trả lời trùng lặp. Điều này trùng lặp câu trả lời này
RousseauAlexandre

19

Tôi muốn chia sẻ giải pháp của mình cho "vấn đề". Tôi chưa phát minh lại bánh xe nhưng cố gắng tìm giải pháp dựa trên những gì JavaScript đã làm. Ưu điểm là, bạn nhận được tất cả các chuyển đổi ngầm định miễn phí. Đặt thuộc tính nguyên mẫu $ of String cung cấp một cú pháp rất hay và gọn (xem các ví dụ bên dưới). Nó có thể không phải là cách hiệu quả nhất, nhưng trong hầu hết các trường hợp xử lý đầu ra, nó không phải được siêu tối ưu hóa.

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

Đây là vài ví dụ:

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'

thật không may, ít nhất # và + không được triển khai cho số float. đây là một tài liệu tham khảo cho các chức năng trong c: tutorialspoint.com/c_standard_library/c_function_sprintf.htm
Daniel


14

Tôi sử dụng một thư viện nhỏ có tên String.format cho JavaScript , hỗ trợ hầu hết các khả năng của chuỗi định dạng (bao gồm định dạng số và ngày) và sử dụng cú pháp .NET. Bản thân tập lệnh nhỏ hơn 4 kB, vì vậy nó không tạo ra nhiều chi phí.


Tôi đã xem thư viện đó và nó trông thực sự tuyệt vời. Tôi đã bực mình khi thấy rằng tải xuống là một EXE. Cái quái gì thế này? Không tải xuống.
jessegavin

Thông thường một kho lưu trữ có thể tải xuống đó là EXE không gì khác hơn là "ZIP tự giải nén". Thực thi nó, và nó sẽ tự giải nén. Điều này khá thuận tiện NHƯNG vì nó trông rất giống phần mềm độc hại, định dạng không được sử dụng trên web thường xuyên nữa.
Chuck Kollars

Mặc dù liên kết này có thể trả lời câu hỏi, tốt hơn là bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi.
starmole

@starmole liên kết là một thư viện javascript 4 kB (rút gọn) . Tôi không tin dán nó vào câu trả lời là một ý tưởng tốt.
ivarni

Bạn đang dán đúng nó sẽ không tốt hơn. Tôi chỉ nhận được nhận xét này để đánh giá ngẫu nhiên - và nhận xét trước khi không thích nó. Đối với tôi stackoverflow tốt hơn khi cung cấp các giải thích thay vì các giải pháp đã sẵn sàng (mà liên kết là). Tôi cũng không muốn khuyến khích mọi người đăng hoặc tải xuống mã hộp đen.
starmole

14

Rất thanh lịch:

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

Tín dụng đi đến (liên kết bị hỏng) https://gist.github.com/0i0/1519811


Đây là người duy nhất xử lý dấu ngoặc thoát {{0}}cũng như những thứ như thế {0}{1}.format("{1}", "{0}"). Nên ở trên đỉnh!
Juan

11

Nếu bạn đang tìm cách xử lý hàng nghìn dấu phân cách, bạn thực sự nên sử dụng toLocaleString () từ lớp Số JavaScript vì nó sẽ định dạng chuỗi cho vùng của người dùng.

Lớp Ngày JavaScript có thể định dạng ngày và giờ địa phương.


1
Đây thực sự là một thiết lập của người dùng như một cài đặt trong ứng dụng (không phải máy của họ) nhưng tôi sẽ xem xét, cảm ơn
Chris S

thêm một số ví dụ để mọi người có thể hiểu nó một cách nhanh chóng.
Bhushan Kawadkar


9

Tôi sử dụng cái này:

String.prototype.format = function() {
    var newStr = this, i = 0;
    while (/%s/.test(newStr))
        newStr = newStr.replace("%s", arguments[i++])

    return newStr;
}

Sau đó, tôi gọi nó:

"<h1>%s</h1><p>%s</p>".format("Header", "Just a test!");

9

Tôi có một giải pháp rất gần với Peter's, nhưng nó liên quan đến số lượng và trường hợp đối tượng.

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

Có lẽ nó còn tốt hơn để giải quyết tất cả các trường hợp sâu, nhưng đối với nhu cầu của tôi thì điều này là tốt.

"This is an example from {name}".format({name:"Blaine"});
"This is an example from {0}".format("Blaine");

PS: Chức năng này rất tuyệt nếu bạn đang sử dụng các bản dịch trong các khung mẫu như AngularJS :

<h1> {{('hello-message'|translate).format(user)}} <h1>
<h1> {{('hello-by-name'|translate).format( user ? user.name : 'You' )}} <h1>

Trong đó en.json giống như

{
    "hello-message": "Hello {name}, welcome.",
    "hello-by-name": "Hello {0}, welcome."
}

phần [^}] trong regrec là không cần thiết .. thay vào đó, hãy sử dụng {(. *?)} hoặc tốt hơn {([\ s \ S] *?)} để khớp với dòng mới.
rawiro

7

Một phiên bản rất khác nhau, phiên bản tôi thích (phiên bản này sử dụng mã thông báo {xxx} thay vì {0} được đánh số, đây là tài liệu tự nhiều hơn và phù hợp với nội địa hóa tốt hơn nhiều):

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

Một biến thể sẽ là:

  var formatted = l(this);

gọi hàm l () trước tiên.



6

Đối với những người thích Node.JSutil.formattính năng của nó , tôi vừa trích xuất nó thành dạng JavaScript vanilla của nó (chỉ có các chức năng sử dụng.format sử dụng):

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

Thu hoạch từ: https://github.com/joyent/node/blob/master/lib/util.js


6

Đối với định dạng cơ bản:

var template = jQuery.validator.format("{0} is not a valid value");
var result = template("abc");

5

Tôi có một trình định dạng dài hơn một chút cho JavaScript ở đây ...

Bạn có thể định dạng một số cách:

  • String.format(input, args0, arg1, ...)
  • String.format(input, obj)
  • "literal".format(arg0, arg1, ...)
  • "literal".format(obj)

Ngoài ra, nếu bạn đã nói ObjectBase.prototype.format (chẳng hạn như với DateJS ) thì nó sẽ sử dụng nó.

Ví dụ ...

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

Tôi cũng đã đặt bí danh với .asFormat và có một số phát hiện trong trường hợp đã có một chuỗi.format (chẳng hạn như với Bộ công cụ MS Ajax (Tôi ghét thư viện đó).


5

Chỉ trong trường hợp ai đó cần một chức năng để ngăn chặn phạm vi gây ô nhiễm toàn cầu, đây là chức năng thực hiện tương tự:

  function _format (str, arr) {
    return str.replace(/{(\d+)}/g, function (match, number) {
      return typeof arr[number] != 'undefined' ? arr[number] : match;
    });
  };

3

Chúng ta có thể sử dụng một thư viện hoạt động chuỗi String.Format nhẹ đơn giản cho Typecript.

Chuỗi.Format ():

var id = image.GetId()
String.Format("image_{0}.jpg", id)
output: "image_2db5da20-1c5d-4f1a-8fd4-b41e34c8c5b5.jpg";

Định dạng chuỗi cho specifier:

var value = String.Format("{0:L}", "APPLE"); //output "apple"

value = String.Format("{0:U}", "apple"); // output "APPLE"

value = String.Format("{0:d}", "2017-01-23 00:00"); //output "23.01.2017"


value = String.Format("{0:s}", "21.03.2017 22:15:01") //output "2017-03-21T22:15:01"

value = String.Format("{0:n}", 1000000);
//output "1.000.000"

value = String.Format("{0:00}", 1);
//output "01"

Định dạng chuỗi cho các đối tượng bao gồm các chỉ định:

var fruit = new Fruit();
fruit.type = "apple";
fruit.color = "RED";
fruit.shippingDate = new Date(2018, 1, 1);
fruit.amount = 10000;

String.Format("the {type:U} is {color:L} shipped on {shippingDate:s} with an amount of {amount:n}", fruit);
// output: the APPLE is red shipped on 2018-01-01 with an amount of 10.000

2

Tôi không thấy String.formatbiến thể:

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

2

Để sử dụng với các hàm thành công của jQuery.ajax (). Chỉ truyền một đối số và chuỗi thay thế bằng các thuộc tính của đối tượng đó là {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;
};

Thí dụ:

var userInfo = ("Email: {Email} - Phone: {Phone}").format({ Email: "someone@somewhere.com", Phone: "123-123-1234" });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.