суть укладывается в 2 строчки
x = 'x';
s = '';
s += x; /* Now s = 'x' */
x += x; /* Now x = 'xx' */
x += x; /* Now x = 'xxxx' */
x += x; /* Now x = 'xxxxxxxx' */
s += x; /* Now s = 'xxxxxxxxx' as desired */
it's bullshit.
function stringFill3(x, n) {
var s = '';
for (;;) {
if (n & 1) s += x;
n >>= 1;
if (n) x += x;
else break;
}
return s;
}
it's better.
(
по скорости, конечно же)
и всё.
осталось только проанализировать, КАК побитовые операции с числами могут иметь какой-то толк с НЕчислами.
PS
насчёт скорости. разница в 1.8 раза в FF. в хроме коэффициент 2.5.
PSS краткий разбор (если можно так назвать) этого кода.
function stringFill3(x, n) {
var s = '';
for (;;) {
if (n & 1) s += x;
n >>= 1;
if (n) x += x;
else break;
}
return s;
}
сначала создаёт
s (результат), далее идёт "бесконечный" цикл (потому что будет работать, пока не прервёшь). таким образом, можно было не выпендриваться и написать цикл через while. и смотрелось бы понятнее.
в каждой итерации цикла к строке
s прибавляется, если
n & 1. да, конечно, мы все знаем, что
& возвращает единичку только для единичек, но что это значит на практике ?
распишем двоичные представления чисел от 1 до 5 (включительно)
Код:
|
1 0001
2 0010
3 0011
4 0100
5 0101 |
операция
<число> & 1 будет возвращать
1 для тех чисел, у которых последняя цифра (
1 для 5,
0 для 4) совпадает с
1 (т.к. единица осталась единицей, то совпадение считается только по последней колонке. если бы вместо единицы с правой стороны оператора было какое-нибудь
0101110, то совпадения высчитывалось для всех пар)
т.е. если мы пройдёмся по всем цифрам из
[1,5] с
& 1 , то получим это :
1 1
2 0
3 1
4 0
5 1
проверку на нечётность не напоминает ? таким образом ,
<число> & 1 эквивалентно проверке числа на
нечётность. (
<число> % 2)
идём дальше.
n >> 1 будет, как известно, будет сдвигать биты один раз (с правой стороны) в числе n. но что это значит ? возьму тот же промежуток.
Код:
|
1 0001
2 0010
3 0011
4 0100
5 0101 |
если мы сделаем
2 >> 1, то сдвинем биты в числе 2 в двоичном представлении вправо один раз.
Код:
|
1 = 0001
1 >> 1
0000 (0)
2 = 0010
2 >> 1
0001 (1)
5 = 0101
5 >> 1
0010 (2) |
в итоге, для того промежутка
<число> >> 1 будет иметь такой результат :
0 0
1 0
2 1
3 1
4 2
5 2
похоже на итератор (--,++)
if (n) x += x; будет работать, пока n не дойдёт до нуля. т.к. перед этой проверкой стоит сдвиг вправо, то, можно сказать, цикл кончится (там break дальше, я не включил), когда n станет равным 0. т.е. на каждой итерации к
строке добавления (строка результата -
s) будет добавляться она же. что это значит?
посмотрим.
x = 'x';
n = 5;
s = '';
// I итерация, n = 5
n & 1 == 1 /*=>*/ s = s + x; // s = 'x'.
n = n >> 1; // n = 2
x = x+x; // 'xx';
// II, n = 2
n & 1 === 0;
n = n >> 1; // n = 1
x = x+x;// 'xx' + 'xx' => 'xxxx'
// III, n = 1
n & 1 /*=>*/ s = s+x; // 'x'+'xxxx' => 'xxxxx'
n = n >> 1 // n = 0
n == 0 /*=>*/ break
// res : 'xxxxx'.
Вывод :
обычный цикл для повторения строки, но оптимизированный :- заменой всех операций с числами на побитовые (переход от десятичной системе к двоичной)
- уменьшением количества итераций в несколько раз