This is the 28th day of my participation in the August Challenge.

The premise

The front end, on the other hand, often deals with values and times. So the formatting of values and times is necessary. Recently has been in the interview front, gave a numerical value to add thousands of interview questions.

As for the answer, one is based on your existing knowledge and the other is knowledge. Some people say, not a thousandth bit, minutes to solve you, re long live. Yes, re is cool, but what about performance?

I love a tight bullshit book. Okay, let’s move on to the main text.

implementation

Some of the following methods can be modified to be more generic, such as adding # instead of adding.

Numeric to string traversal

function format_with_array(number) {
    var arr = (number + ' ').split('. ');
    var int = arr[0].split(' ');
    var fraction = arr[1] | |' ';
    var r = "";
    var len = int.length;
    int.reverse().forEach(function (v, i) {
        if(i ! = =0 && i % 3= = =0) {
            r = v + "," + r;
        } else{ r = v + r; }})returnr + (!! fraction ?"." + fraction : ' ');
}
Copy the code

substring

function format_with_substring(number) {
    var arr = (number + ' ').split('. ');
    var int = arr[0] + ' ';
    var fraction = arr[1] | |' ';
    var f = int.length % 3;
    var r = int.substring(0, f);

    for (var i = 0; i < Math.floor(int.length / 3); i++) {
        r += ', ' + int.substring(f + i * 3, f + (i + 1) * 3)}if (f === 0) {
        r = r.substring(1);
    }
    returnr + (!! fraction ?"." + fraction : ' ');
}
Copy the code

Division plus modulo

function format_with_mod(number) {
    var n = number;
    var r = ""; 
    var temp;
    do {
        mod = n % 1000;
        n = n / 1000;
        temp = ~~mod;
        r =  (n > 1 ?`${temp}`.padStart(3."0"): temp) + (!! r ?"," + r : "")}while (n > 1)

    var strNumber = number + "";
    var index = strNumber.indexOf(".");
    if (index > 0) {
        r += strNumber.substring(index);
    }
    return r;
}
Copy the code

regular

function format_with_regex(number) {
    var reg = / \ d {1, 3} (? =(\d{3})+$)/g;
    return (number + ' ').replace(reg, '$&,);
}

function format_with_regex(number) {
    var reg = /(\d)(? = (? :\d{3})+$)/g   
    return (number + ' ').replace(reg, '$1');
}

Copy the code

toLocaleString

function format_with_toLocaleString(number, minimumFractionDigits, maximumFractionDigits) {
    minimumFractionDigits = minimumFractionDigits || 2;
    maximumFractionDigits = (maximumFractionDigits || 2);
    maximumFractionDigits = Math.max(minimumFractionDigits, maximumFractionDigits);

    return number.toLocaleString("en-us", {
        maximumFractionDigits: maximumFractionDigits || 2.minimumFractionDigits: minimumFractionDigits || 2})}Copy the code

Intl.NumberFormat

function format_with_Intl(number, minimumFractionDigits, maximumFractionDigits) {
    minimumFractionDigits = minimumFractionDigits || 2;
    maximumFractionDigits = (maximumFractionDigits || 2);
    maximumFractionDigits = Math.max(minimumFractionDigits, maximumFractionDigits);

    return new Intl.NumberFormat('en-us', {
        maximumFractionDigits: maximumFractionDigits || 2.minimumFractionDigits: minimumFractionDigits || 2
    }).format(number)
}
Copy the code

performance

To test with and without decimal places, remove decimal places if the random value is greater than 0.5 on getData.

function getData(count) {
    var data = new Array(count).fill(0).map(function (i) {
        var rd = Math.random();
        var r = rd * Math.pow(10.10);
        if (rd > 0.5) {
            r = ~~r;
        }
        return r
    })
    return data;
}

function test(data, fn, label) {
    var start = performance.now();
    for (var i = 0; i < data.length; i++) {
        fn(data[i]);
    }
    var time = performance.now() - start;

    message((fn.name || label) + ":" + time + "ms");
}


function executeTest() {
    var data = getData(+textCount.value);
    test(data, format_with_array);
    test(data, format_with_mod);
    test(data, format_with_substring);
    test(data, format_with_regex);
    test(data, format_with_toLocaleString);
    test(data, format_with_Intl);
}

function message(msg) {
    var el = document.createElement("p");
    el.innerHTML = msg;
    messageEl.appendChild(el);
}

Copy the code

Test data

1. Chrome Version 74.0.3729.131 (official) (32-bit)

Format_with_array: 59.13 ms

Format_with_mod: 23.96 ms

Format_with_substring: 44.04 ms

Format_with_regex: 53.54 ms

Format_with_toLocaleString: 1813.61 ms

Format_with_Intl: 1973.45 ms

2. 360 speed browser 11.0.2052.0 speed mode

Format_with_array: 63.30 ms

Format_with_mod: 37.80 ms

Format_with_substring: 41.40 ms

Format_with_regex: 51.20 ms

Format_with_toLocaleString: 3334.30 ms

Format_with_Intl: 3485.80 ms

Compatibility mode does not support array. fill Pass

3. Sogou high-speed browser 8.5.10.30358

Format_with_array: 75.29 ms

Format_with_mod: 35.47 ms

Format_with_substring: 40.79 ms

Format_with_regex: 49.86 ms

Format_with_toLocaleString: 2418.04 ms

Format_with_Intl: 2474.30 ms

4. firefox 66.0.3

Format_with_array: 41.00 ms

Format_with_mod: 25.00 ms

Format_with_substring: 28.00 ms

Format_with_regex: 43.00 ms

Format_with_toLocaleString: 1799.00 ms

Format_with_Intl: 2239.00 ms

The basic results are the same, and the results will occasionally be inconsistent because of different random numbers.

format_with_mod > format_with_substring > format_with_regex > format_with_array > format_with_toLocaleString > format_with_Intl

There’s a lot of room for Intl.NumberFormat to improve things like caching instances.

Of course, the test may not be rigorous, the problem is not big, know that there are several ideas on the line, what other ideas? Welcome to leave a message.

Write in the last

If you think it is good, your likes and comments are the biggest motivation for me to move forward.

Please go to the technical exchange groupCome here,. Or add my wechat Dirge-Cloud and learn together.