En af de statiske metoder på String objektet, som jeg bruger aller mest, er Format(strig format, object[] args). Ikke kun fordi den er en let og elegant wrapper om StringBuilder, men også fordi den gør min kode noget lettere at læse. Alle har vel prøvet at lave noget lignende dette:
var str = "Besked: " + emne + "\nFra: " + afsender + "\nIndhold: " body;
Eller endnu værre:
document.write("Besked: " + emne + "
Fra: " + afsender + "
Indhold:
" + body + "
");
Hvor er det bare meget lettere med:
string.Format("Besked: {0}
Fra: {1}
Indhold:
{2}
", emne, afsender, body);
Hvad nu når man befinder sig i JavaScript? Her findes der ingen format funktion. Hvor meget skal der til for at implementerer noget lignende?
Lad os starte med at vedtage at vi bruger samme format-syntaks , som i c#:
Altså man kan skrive sit format med 1-10 bindingsudtryk. Hvert bindingsudtryk kapsles ind i ‘tuborg’ klammer. Vi skal så bare lave et regulært udtryk, som kan fiske disse bindingsudtryk ud:
var re = RegExp("\\{(\\d)\\}", "g");
// Eller kort:
var re = /\{(\d)\}/g;
Dette udtryk vil fange alle vores bindingsudtryk, og samtidig fange en gruppe med index (paranteserne om \d);
Alt hvad man så skal, er at pakke en funktion uden om udtrykket. Jeg har et script-bibliotek med disse grundliggende funktioner, så jeg laver funktionen som en udviddelse af String-objektet.
String.prototype.format = function() {
var re = new RegExp("\\{(\\d)\\}", "g");
var params = arguments;
var builder = this.replace(re, function() {
if (arguments.length > 2) {
if (arguments[1] >= params.length)
throw new Error("String.format: Bindingsudtryk stemmer ikke over ens med antal af argumenter");
return params[arguments[1]];
}
});
return builder;
}
Det vigtigste i den extension, er linjen hvor arguments bliver ‘boxet’ til args, for så at blive overleveret til replace metodens callback-funktion via closure. Med dette script inkluderet, kan man nu skrive følgende:
"Besked: {0}\nFra: {1}\nIndhold: {2}"
.format(emne, afsender, body);
”Code {0}. . .”.format(“On”);