JavaScript шаблонизация строки, подстановка параметров - printf() sprintf() функция, реализация, Пример кода

В сети (см. источник ниже) имеется такая вот реализация функции для подстановки значений в шаблон строки, далее приведу её код (вместе с одним расширением прототипа String, от которого она зависит), слегка отредактированный и приспособленный работе в строгом режиме:

"use strict";

/*
 * The padding functions
 * @see @link http://forum.dklab.ru/viewtopic.php?p=57...
 * 
 * @returns {sprintf.result|String}
 */ 
String.prototype.padding = function(n, c)
{
    if (!c) c = " ";
    if (c.length > 1) c = c.charAt(0);
    var val = this.valueOf();
    var pad = c.repeat(Math.abs(n) - this.length);
    if (n < 0)
        return val + pad;
    return pad + val;
}

/**
 * 
 * @see @link http://forum.dklab.ru/viewtopic.php?p=57...
 * 
* sprintf(format, argument_list)
*
* The string function like one in C/C++, PHP, Perl
* Each conversion specification is defined as below:
*
* %[index][alignment][padding][width][precision]type
*
* index     - An optional index specifier that changes the order of the
*             arguments in the list to be displayed.
* alignment - An optional alignment specifier that says if the result should be
*             left-justified or right-justified. The default is
*             right-justified; a "-" character here will make it left-justified.
* padding   - An optional padding specifier that says what character will be
*             used for padding the results to the right string size. This may
*             be a space character or a "0" (zero character). The default is to
*             pad with spaces. An alternate padding character can be specified
*             by prefixing it with a single quote ('). See the examples below.
* width     - An optional number, a width specifier that says how many
*             characters (minimum) this conversion should result in.
* precision - An optional precision specifier that says how many decimal digits
*             should be displayed for floating-point numbers. This option has
*             no effect for other types than float.
* type      - A type specifier that says what type the argument data should be
*             treated as. Possible types:
*
* % - a literal percent character. No argument is required. 
* b - the argument is treated as an integer, and presented as a binary number.
* c - the argument is treated as an integer, and presented as the character
*     with that ASCII value.
* d - the argument is treated as an integer, and presented as a decimal number.
* u - the same as "d".
* f - the argument is treated as a float, and presented as a floating-point.
* o - the argument is treated as an integer, and presented as an octal number.
* s - the argument is treated as and presented as a string.
* x - the argument is treated as an integer and presented as a hexadecimal
*     number (with lowercase letters).
* X - the argument is treated as an integer and presented as a hexadecimal
*     number (with uppercase letters).
*/
function sprintf()
{
    var args = arguments;
    var frmt = arguments[0].replace(/%%/g, "\0\0");
    var result = "", prev = 0, index = 0;
    var re = /%(\d+[\$#])?([+-])?('.|0| )?(\d*)(\.\d*)?([bcdfosuxX])/g;
    /*
    * The re.exec() method returns the array with the following properties
    * witch are used in this function
    *    x.index contains the substring position found at the origin string
    *    x[0] contains the found substring
    *    x[1] contains the index specifier (as \d+\$ or \d+#)
    *    x[2] contains the alignment specifier ("+" or "-" or empty)
    *    x[3] contains the padding specifier (space char, "0" or defined as '.)
    *    x[4] contains the width specifier (as \d*)
    *    x[5] contains the floating-point precision specifier (as \.\d*)
    *    x[6] contains the type specifier (as [bcdfosuxX])
    */
    var x;
    while (x = re.exec(frmt)) {
        index++;
        if (x[1]) var ins = args[x[1].substring(0, x[1].length - 1)];
        else var ins = args[index];
        switch (x[6]) {
        case "b":
            ins = Number(ins).toString(2);
            break;
        case "c":
            ins = String.fromCharCode(ins);
            break;
        case "d":
        case "u":
            ins = Number(ins).toString(10);
            break;
        case "f":
            ins = Number(ins);
            if (x[5].length > 1) ins = ins.toFixed(x[5].substr(1));
            else ins = ins.toExponential(x[4]);
            break;
        case "o":
            ins = Number(ins).toString(8);
            break;
        case "s":
            ins = ins.toString();
            break;
        case "x":
            ins = Number(ins).toString(16);
            break;
        case "X":
            ins = Number(ins).toString(16).toUpperCase();
            break;
        }
        result += frmt.substring(prev, x.index);
        prev = x.index + x[0].length;
        if (!x[3]) x[3] = "";
        result += ins.padding(x[2] + x[4], x[3].substr(x[3].length - 1));
    }
    if (prev < frmt.length) result += frmt.substr(prev);
    result = result.replace(/\0\0/g, "%");
    return result;
}

Пример использования:

format = "The %2\$s contains %1\$d monkeys";
var s = sprintf(format, 5, "tree"); // s == "The tree contains 5 monkeys"
var s = sprintf(format, "tree", 5); // s == "The 5 contains NaN monkeys" 

Источник: http://forum.dklab.ru/viewtopic.php?p=57...

Key Words for FKN + antitotal forum (CS VSU):