Как стать автором
Обновить

Комментарии 29

А где вы взяли firefox 44? FF43 только сегодня должен стать Developer Edition. Или я чего то не понимаю?
Это ночная сборка, только сегодня версия сменилась.
Наивная сборка строки через slice работает быстрее регулярок:
var s = i.toString();
var o = [];
var l = s.length;
var off = l % 3;
var groups = Math.floor(l / 3);
var x;
if (off) {
  o.push(s.slice(0, off));
}
for (x = 0; x < groups; x++) {
  o.push(s.slice(off, off += 3));
}
var result = o.join("'");
console.log(result)
Чудеса)

У меня:
Хром:

regex:        985.489ms
nativeSlice:  393.228ms
regex:       1030.108ms
nativeSlice:  398.542ms
regex:       1016.810ms
nativeSlice:  412.375ms

Firefox:

regex:       608.23ms
nativeSlice: 999.5ms
regex:       573.7ms
nativeSlice: 898.71ms
regex:       613.18ms
nativeSlice: 933.68ms

IE:

regex:       1 766,432 мс
nativeSlice: 1 702,35 мс
regex:       1 651,024 мс
nativeSlice: 1 684,765 мс
regex:       1 760,125 мс
nativeSlice: 1 690,707 мс

Node.js:

regex:       667ms
nativeSlice: 374ms
regex:       748ms
nativeSlice: 392ms
regex:       764ms
nativeSlice: 380ms
В Хроме и особенно в IE скорость выполнения может сильно меняться в зависимости от того, открыты ли инструменты разработчика. Вероятно, какие-то оптимизации отключаются. FF в этом вроде бы не замечен (ну, во всяком случае, чтобы сильно).
Добавил в конец поста данные по вашему варианту.
Наивная сборка строки через числа работает быстрее наивной сборки через slice:
function mathPower (num){
    if (num < 999)
        return num;
    return mathPower(~~(num / 1000)) + "'"
           + ("00"+(~~(num % 1000))).substr(-3,3);
}

jsfiddle.net/5nzL3yLo
Спасибо. Попробовал в Node.js и консолях:

результат регулярки плюс по три результата вашего варианта
Node.Js

[ 0, 64840650 ]

[ 0, 16904683 ]
[ 0, 14002223 ]
[ 0, 15718417 ]

Chrome

 80

102
101
 98

Firefox

218

214
218
239

IE

215

193
204
186

Обновил конец статьи, добавил ваш вариант в тесты. У меня он выиграл на IE.
… если вы знаете нужную локаль заранее, лучше воспользоваться заменой по регулярному выражению…

Вы же сами пишете выше про конструктор. Да, как только вам стала известна локаль, то для Intl лучше предварительно создавать эм… форматтер
new Intl.NumberFormat([locales[, options]])

В таком случае он работает достаточно быстро. А регулярки не обеспечат вам поддержку всех локалей, Китайские, японские цифры или иврит все вам поломают, намучаетесь.
Да, пожалуй, если сложный случай, тем более — если дело не только в разделении на группы, лучше положиться на проверенные стандарты. Но если случай простой, всего лишь разделить запятыми или пробелами, и важна скорость, то можно, наверное, и регуляркой ограничиться.
Вот этот способ в пять раз быстрее регулярки:
var s = i.toString();
var l = s.length;
var result = '';

if (l > 15) result += s.slice(-18, -15) + "'";
if (l > 12) result += s.slice(-15, -12) + "'";
if (l > 9) result += s.slice(-12, -9) + "'";
if (l > 6) result += s.slice(-9, -6) + "'";
if (l > 3) result += s.slice(-6, -3) + "'";
result += s.slice(-3);
То есть вы полагаетесь на длину Number.MAX_SAFE_INTEGER? Интересное практичное упрощение.

У меня (небольшой прирост только в Node.js):

Регулярка vs по три теста вашего способа
Хром:

80

99
97
99

Firefox:

218

599
633
656

IE:

215

377
370
358

Node.js:

[ 0, 64840650 ]

[ 0, 46075947 ]
[ 0, 53800444 ]
[ 0, 43452631 ]


Добавил в конец поста данные по вашему варианту.
function fmt(n) {
    n = n.toString();
    const l = n.length;
    var s='',
        i=0;
    while(i<l){
        if((l-i)%3 || !i){
            s+=n[i++];
        }else{
            s+=','+n[i++];
        }
    }
    return s;
}
Спасибо!

Проверил, вроде бы по сравнению с регуляркой получается быстрее везде, кроме IE. Вот результаты — по три запуска, сначала регулярка, потом ваш вариант.

Результаты
Node.Js

[ 0, 72634428 ]
[ 0, 35303136 ]

[ 0, 73739665 ]
[ 0, 38605069 ]

[ 0, 85149363 ]
[ 0, 39749604 ]

Chrome

98
36

119
36

91
34

Firefox

214
185

224
186

220
182

IE

186
266

175
277

185
302


А Вы на лэптопе тестируете? Посмотрите в настройках Advanced Power Settings-> Internet Explorer -> Javascript Timer Frequency, там должно быть Maximum Perfomance
Да, но он работает от сети. Проверил, там при работе от сети стоит «Максимальная производительность».
Обновил конец статьи, добавил ваш вариант в тестовую страницу. У меня он выиграл на Firefox.
И еще
function fmt2(n) {
    var s='';
    while(n){
        s=('000'+n%1000).slice(n>=1000 ? -3 : -n.toString().length)+s;
        n=n/1000|0;
        if(n) {
            s=','+s;
        }
    }
    return s;
}
Спасибо. Новая табличка. В Хроме более чем в два раза быстрее предыдущего, в IE чуть медленнее, а вот в Firefox почему-то более чем в два раза медленнее по сравнению с fmt1:

Скриншоты:





Плюс самый разжёванный вариант (см. P.S. 4 в конце статьи).
Нет смысла заново инициализировать регулярку. Так же быстрее:

var pattern = new RegExp('\B(?=(?:\d{3})+$)', 'g');

i.toString().replace( pattern , ',' ); //А это в цикле

upd: Прошлый комментарий отменяется. Увидел в тестах.
Всё равно спасибо)
и он оказался довольно быстрым, а в тестах на Firefox даже занял первое место.
Я вижу, что во всех браузерах, кроме IE11, slice_concatenate имеет наибольшую скорость работы. exhaustion на 3-5 местах. Может, я не туда смотрю?
У них какой-то баг на сайте. Кажется, ни один из моих тестов на Firefox Nightly 44.0a1 не сохранился и не отображается в сведённых чартах, хотя после каждого теста в текущей табличке всё отображается. Может, при распознавании ночных сборок у них сбой происходит.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории