jQuery에서 String.format과 동일


답변:


193

ASP.NET AJAX소스 코드는 참조 용으로 제공되므로이를 선택하여 계속 사용하려는 부분을 별도의 JS 파일에 포함시킬 수 있습니다. 또는 jQuery로 이식 할 수 있습니다.

포맷 기능은 다음과 같습니다.

String.format = function() {
  var s = arguments[0];
  for (var i = 0; i < arguments.length - 1; i++) {       
    var reg = new RegExp("\\{" + i + "\\}", "gm");             
    s = s.replace(reg, arguments[i + 1]);
  }

  return s;
}

그리고 여기 프로토 타입 함수로 끝과 끝이 있습니다 ...

String.prototype.endsWith = function (suffix) {
  return (this.substr(this.length - suffix.length) === suffix);
}

String.prototype.startsWith = function(prefix) {
  return (this.substr(0, prefix.length) === prefix);
}

2
많은 것이 보이지 않는 것 같습니다. JavaScript 버전에는 모든 멋진 숫자 서식이 없습니다. blog.stevex.net/index.php/string-formatting-in-csharp
Nosredna

와우 이것에 대한 많은 감사합니다, 사실은 이미 이것에 대해 생각하지만 또한 마이크로 소프트 관대 한 라이센스하에 발표 몰랐다,이 때문에 라이센스의 불가능하다고 생각
왈 리드 Eissa

23
라이센스 또는 라이센스 없음. 아주 간단한 것을 작성하는 올바른 방법은 하나뿐입니다
adamJLev

1
형식이 호출 될 때마다 각각의 모든 인수에 대해 RegEx 객체를 생성 (및 폐기)하면 가비지 수집기에 초과 사용이 발생할 수 있습니다.
mckoss

14
경고 :이 반복적으로 포맷합니다 : 그래서 만약 당신이 {0}{1}, {0}첫번째 교체, 그리고 모든 발생됩니다 {1}이미 대체 텍스트와 원래 형식으로 모두 대체됩니다에.
Zenexer

147

이것은 Josh가 게시 한 기능의 더 빠르고 간단하고 프로토 타입입니다.

String.prototype.format = String.prototype.f = function() {
    var s = this,
        i = arguments.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
    }
    return s;
};

용법:

'Added {0} by {1} to your collection'.f(title, artist)
'Your balance is {0} USD'.f(77.7) 

나는 이것을 너무 많이 사용하여 별명을 지정 f했지만 더 자세한 정보를 사용할 수도 있습니다 format. 예 :'Hello {0}!'.format(name)


1
최신 브라우저로 훨씬 더 간단한 방법이 있습니다 stackoverflow.com/a/41052964/120296
데이비드

3
@ david 템플릿 문자열은 전혀 동일하지 않습니다. 그것들은 문자열 연결을위한 구문 설탕이며 형식화와 같지는 않지만 훌륭합니다. 따라서 즉시 실행되므로 교체 시점의 범위가 대체 시점이어야합니다. 이 때문에 텍스트 파일이나 데이터베이스에 저장할 수 없습니다. 사실, 그것들을 어디에나 저장하는 유일한 방법은 그것들을 기능에 넣는 것입니다. 형식화 된 문자열 함수는 변수 이름에 신경 쓰지 않는 위치 대체를 사용합니다.
krowe2

131

Julian Jelfs를 제외한 위의 많은 함수에는 다음 오류가 포함되어 있습니다.

js> '{0} {0} {1} {2}'.format(3.14, 'a{2}bc', 'foo');
3.14 3.14 afoobc foo

또는 인수 목록 끝에서 거꾸로 계산되는 변형의 경우 :

js> '{0} {0} {1} {2}'.format(3.14, 'a{0}bc', 'foo');
3.14 3.14 a3.14bc foo

다음은 올바른 기능입니다. Julian Jelfs 코드의 프로토 타입 변형으로 조금 더 빡빡했습니다.

String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{(\d+)\}/g, function (m, n) { return args[n]; });
};

그리고 여기에 약간 더 고급 버전이 있으며 중괄호를 두 배로 늘릴 수 있습니다.

String.prototype.format = function () {
  var args = arguments;
  return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
    if (m == "{{") { return "{"; }
    if (m == "}}") { return "}"; }
    return args[n];
  });
};

이것은 올바르게 작동합니다 :

js> '{0} {{0}} {{{0}}} {1} {2}'.format(3.14, 'a{2}bc', 'foo');
3.14 {0} {3.14} a{2}bc foo

다음은 Blair Mitchelmore의 또 다른 좋은 구현입니다. https://web.archive.org/web/20120315214858/http://blairmitchelmore.com/javascript/string.format


그리고 내가 너무 자세히 보지 않았지만 {0 : + $ #, 0.00;-$ #, 0.00; 0}과 같은 형식을 구현하는 것으로 보이는 또 하나는 다음과 같습니다. masterdata.dyndns.org/r/string_format_for_javascript
gpvos

아, 그리고 파이썬 보간 형식을 사용하는 것 : code.google.com/p/jquery-utils/wiki/…
gpvos

형식 구현은 내가 위로를 위해 이동이 코멘트를 언급 masterdata.se/r/string_format_for_javascript
gpvos

참고 :이 페이지의 다른 곳에서 ianj의 대답을 사용하면 숫자 매개 변수 대신 명명 된 이름을 사용할 수 있습니다. 그의 메소드를 프로토 타입을 사용하는 메소드로 변경하면 두 번째 매개 변수를 slice.call 함수로 1에서 0으로 변경해야합니다.
gpvos

48

컬렉션이나 배열을 인수로 취하는 형식 함수를 만들었습니다.

용법:

format("i can speak {language} since i was {age}",{language:'javascript',age:10});

format("i can speak {0} since i was {1}",'javascript',10});

암호:

var format = function (str, col) {
    col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1);

    return str.replace(/\{\{|\}\}|\{(\w+)\}/g, function (m, n) {
        if (m == "{{") { return "{"; }
        if (m == "}}") { return "}"; }
        return col[n];
    });
};

5
좋은 점은 누락 된 것입니다. String.prototype.format = function (col) {return format (this, col);}
Erik

10
나는 문자열을 확장하지 않는 것을 선호합니다
ianj

3
사용법에 작은 오타가 있습니다. 두 번째 줄은 다음과 같아야합니다.
기 illa 젠 드레

String.prototype?를 사용하여 확장 문자열을 선호하지 않는 이유는 무엇 입니까?
Kiquenet

36

jQuery.validator.format과 같은 공식 옵션이 있습니다.

jQuery Validation Plugin 1.6 (적어도)과 함께 제공됩니다. .NET
에서 String.Format발견 된 것과 매우 유사합니다 .

편집 깨진 링크를 수정했습니다.



13

Q가 요구하는 것과 정확히 일치하지는 않지만 비슷하지만 번호가 아닌 명명 된 자리 표시자를 사용하는 것을 만들었습니다. 나는 개인적으로 명명 된 인수를 선호하고 객체를 인수로 보내면됩니다 (더 자세하지만 유지하기가 더 쉽습니다).

String.prototype.format = function (args) {
    var newStr = this;
    for (var key in args) {
        newStr = newStr.replace('{' + key + '}', args[key]);
    }
    return newStr;
}

사용법 예는 다음과 같습니다.

alert("Hello {name}".format({ name: 'World' }));

8

EcmaScript 2015 (ES6)를 지원하는 최신 브라우저를 사용하면 템플릿 문자열을 즐길 수 있습니다 . 서식을 지정하는 대신 변수 값을 변수에 직접 삽입 할 수 있습니다.

var name = "Waleed";
var message = `Hello ${name}!`;

템플릿 문자열은 백틱 (`)을 사용하여 작성해야합니다.


6

지금까지 제시된 답변 중 어느 것도 인클로저를 사용하여 한 번 초기화하고 후속 사용을 위해 정규 표현식을 저장하는 데 대한 명확한 최적화가 없습니다.

// DBJ.ORG string.format function
// usage:   "{0} means 'zero'".format("nula") 
// returns: "nula means 'zero'"
// place holders must be in a range 0-99.
// if no argument given for the placeholder, 
// no replacement will be done, so
// "oops {99}".format("!")
// returns the input
// same placeholders will be all replaced 
// with the same argument :
// "oops {0}{0}".format("!","?")
// returns "oops !!"
//
if ("function" != typeof "".format) 
// add format() if one does not exist already
  String.prototype.format = (function() {
    var rx1 = /\{(\d|\d\d)\}/g, rx2 = /\d+/ ;
    return function() {
        var args = arguments;
        return this.replace(rx1, function($0) {
            var idx = 1 * $0.match(rx2)[0];
            return args[idx] !== undefined ? args[idx] : (args[idx] === "" ? "" : $0);
        });
    }
}());

alert("{0},{0},{{0}}!".format("{X}"));

또한 format () 구현이 이미 존재하는 경우 어떠한 예제도 고려하지 않습니다.


2
rx2는 불필요합니다. 제 구현을보십시오. rx1에 (괄호)가 있지만 내부 함수에 전달하는 값을 사용하지 마십시오. 또한 이것이 Javascript 엔진에서 수행하는 명백한 최적화라고 생각합니다 . 최신 브라우저가 아직이 배후에서이 최적화를 수행하지 않습니까? Perl은 1990 년에 그렇게했다. 함수가 이미 구현되었는지 확인하기 위해 랩퍼가 있어야한다.
gpvos

1
또한 (args [idx] === "")에 대한 테스트는 나에게 불필요한 것처럼 보입니다. 정의되지 않은! == ""이기 때문에 이미 해당 줄의 첫 번째 테스트로 덮여 있습니다.
gpvos

4

내 꺼야 :

String.format = function(tokenised){
        var args = arguments;
        return tokenised.replace(/{[0-9]}/g, function(matched){
            matched = matched.replace(/[{}]/g, "");
            return args[parseInt(matched)+1];             
        });
    }

방탄은 아니지만 현명하게 사용하면 작동합니다.


4

늦은 시즌을 지났지 만 방금 주어진 답변을보고 내 tuppence 가치가 있습니다.

용법:

var one = strFormat('"{0}" is not {1}', 'aalert', 'defined');
var two = strFormat('{0} {0} {1} {2}', 3.14, 'a{2}bc', 'foo');

방법:

function strFormat() {
    var args = Array.prototype.slice.call(arguments, 1);
    return arguments[0].replace(/\{(\d+)\}/g, function (match, index) {
        return args[index];
    });
}

결과:

"aalert" is not defined
3.14 3.14 a{2}bc foo

3

이제 템플릿 리터럴을 사용할 수 있습니다 .

var w = "the Word";
var num1 = 2;
var num2 = 3;

var long_multiline_string = `This is very long
multiline templete string. Putting somthing here:
${w}
I can even use expresion interpolation:
Two add three = ${num1 + num2}
or use Tagged template literals
You need to enclose string with the back-tick (\` \`)`;

console.log(long_multiline_string);


3
문자열이 대체 변수와 함께 정의 될 때만 작동한다는 것을 알 때까지 템플릿 리터럴에 대해 흥분했습니다. 저에게는 그것들을 거의 쓸모 없게 만듭니다. 어떤 이유로 든 내 문자열의 대부분은 채우거나 사용하는 코드와 별도로 정의됩니다.
스톤

2

다음은 '{'을 (를) 탈출하고 할당되지 않은 자리 표시자를 정리할 수있는 내 버전입니다.

function getStringFormatPlaceHolderRegEx(placeHolderIndex) {
    return new RegExp('({)?\\{' + placeHolderIndex + '\\}(?!})', 'gm')
}

function cleanStringFormatResult(txt) {
    if (txt == null) return "";

    return txt.replace(getStringFormatPlaceHolderRegEx("\\d+"), "");
}

String.prototype.format = function () {
    var txt = this.toString();
    for (var i = 0; i < arguments.length; i++) {
        var exp = getStringFormatPlaceHolderRegEx(i);
        txt = txt.replace(exp, (arguments[i] == null ? "" : arguments[i]));
    }
    return cleanStringFormatResult(txt);
}
String.format = function () {
    var s = arguments[0];
    if (s == null) return "";

    for (var i = 0; i < arguments.length - 1; i++) {
        var reg = getStringFormatPlaceHolderRegEx(i);
        s = s.replace(reg, (arguments[i + 1] == null ? "" : arguments[i + 1]));
    }
    return cleanStringFormatResult(s);
}

2

다음 대답은 아마도 가장 효율적이지만 인수의 1 대 1 매핑에만 적합하다는 경고가 있습니다. 이것은 문자열을 연결하는 가장 빠른 방법을 사용합니다 (stringbuilder와 유사 : 문자열 배열, 결합 됨). 이것은 내 자신의 코드입니다. 그래도 더 나은 분리기가 필요합니다.

String.format = function(str, args)
{
    var t = str.split('~');
    var sb = [t[0]];
    for(var i = 0; i < args.length; i++){
        sb.push(args[i]);
        sb.push(t[i+1]);
    }
    return sb.join("");
}

다음과 같이 사용하십시오.

alert(String.format("<a href='~'>~</a>", ["one", "two"]));

2
허용되는 답변이 가장 좋습니다. 가능한 한 모든 효율성 (긴 루프)을 짜고 args의 1 : 1 매핑이 필요한 시나리오에서 유용한 고유 한 답변을 제공합니다. 보다 효율적인 cuz replace () 및 new Regex ()는 정규식을 수행 할 때 단일 split ()보다 더 많은 CPU주기를 사용합니다.
Skychan

-1 필요가 없습니다. 아니요, 널리 적용 할 수는 없지만 맞습니다. 약간 더 효율적입니다. 이제 저자에게는 아키텍처 질문이 있습니다. 이러한 종류의 최적화가 필요한 클라이언트 에서 이러한 대규모 데이터 세트 처리하는 응용 프로그램 종류는 무엇 입니까?
Michael Blackburn

좋은 지적 마이클 블랙번. 대부분의 상황은 아마 괜찮을 것입니다. 내 경우에는 좋은 데이터 덩어리 (제품 그룹 내의 제품 변형, 수백 가지 변형)를 처리하고 있었고 사용자는 일반적으로 많은 브라우저 탭을 열고 모든 웹 사이트가 많은 CPU를 빨아들이는 경향이 있다고 생각합니다. 고효율을 유지하기 위해이 구현을 선호했습니다.
Skychan

2

이것은 DRY 원칙을 위반하지만 간결한 솔루션입니다.

var button = '<a href="{link}" class="btn">{text}</a>';
button = button.replace('{text}','Authorize on GitHub').replace('{link}', authorizeUrl);

0
<html>
<body>
<script type="text/javascript">
   var str="http://xyz.html?ID={0}&TId={1}&STId={2}&RId={3},14,480,3,38";
   document.write(FormatString(str));
   function FormatString(str) {
      var args = str.split(',');
      for (var i = 0; i < args.length; i++) {
         var reg = new RegExp("\\{" + i + "\\}", "");             
         args[0]=args[0].replace(reg, args [i+1]);
      }
      return args[0];
   }
</script>
</body>
</html>

이것은 URI에 적합하지만 일반적인 사용법의 경우 하나의 문자열에 형식이 모두 포함되어 있고 구성 요소가 매우 취약합니다. 문자열에 쉼표가 포함되어 있으면 어떻게됩니까?
Michael Blackburn

0

Josh Stodola의 답변을 얻을 수 없었지만 다음이 나를 위해 일했습니다. 의 사양에 유의하십시오 prototype. (IE, FF, Chrome 및 Safari에서 테스트되었습니다.) :

String.prototype.format = function() {
    var s = this;
    if(t.length - 1 != args.length){
        alert("String.format(): Incorrect number of arguments");
    }
    for (var i = 0; i < arguments.length; i++) {       
        var reg = new RegExp("\\{" + i + "\\}", "gm");
        s = s.replace(reg, arguments[i]);
    }
    return s;
}

s정말해야 클론this파괴적인 방법으로되지 않도록,하지만 정말 필요는 없습니다.


파괴적인 방법이 아닙니다. s가 s.replace ()의 반환 값으로 재 지정 될 때, 이것은 그대로 유지됩니다.
gpvos

0

의 adamJLev의 위대한 답변을 확장 하면 다음과 같이 TypeScript 버전이 있습니다.

// Extending String prototype
interface String {
    format(...params: any[]): string;
}

// Variable number of params, mimicking C# params keyword
// params type is set to any so consumer can pass number
// or string, might be a better way to constraint types to
// string and number only using generic?
String.prototype.format = function (...params: any[]) {
    var s = this,
        i = params.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), params[i]);
    }

    return s;
};

0

문자열 프로토 타입에 추가하는 플런저가 있습니다 : string.format 다른 예제만큼 짧지는 않지만 훨씬 더 유연합니다.

사용법은 C # 버전과 유사합니다.

var str2 = "Meet you on {0}, ask for {1}";
var result2 = str2.format("Friday", "Suzy"); 
//result: Meet you on Friday, ask for Suzy
//NB: also accepts an array

또한 이름 및 객체 속성 사용에 대한 지원 추가

var str1 = "Meet you on {day}, ask for {Person}";
var result1 = str1.format({day: "Thursday", person: "Frank"}); 
//result: Meet you on Thursday, ask for Frank

0

이와 같은 대체품으로 어레이를 닫을 수도 있습니다.

var url = '/getElement/_/_/_'.replace(/_/g, (_ => this.ar[this.i++]).bind({ar: ["invoice", "id", 1337],i: 0}))
> '/getElement/invoice/id/1337

또는 당신은 시도 할 수 있습니다 bind

'/getElement/_/_/_'.replace(/_/g, (function(_) {return this.ar[this.i++];}).bind({ar: ["invoice", "id", 1337],i: 0}))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.