Вот улучшение превосходного ответа Doubletap . У оригинала есть два недостатка, которые рассматриваются здесь:
Во-первых, как уже упоминали другие, есть небольшая вероятность создания коротких строк или даже пустой строки (если случайное число равно 0), что может нарушить работу вашего приложения. Вот решение:
(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
Во-вторых, и оригинал, и приведенное выше решение ограничивают размер строки N до 16 символов. Следующее вернет строку размера N для любого N (но учтите, что использование N> 16 не увеличит случайность и не уменьшит вероятность столкновений):
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
Пояснение:
- Выберите случайное число в диапазоне [0,1), то есть от 0 (включительно) до 1 (исключая).
- Преобразовать число в строку base-36, т. Е. С помощью символов 0-9 и a-z.
- Блокнот с нулями (решает первую проблему).
- Отрежьте ведущий '0.' префикс и дополнительные нули дополнения.
- Повторите строку достаточное количество раз, чтобы в ней было хотя бы N символов (путем объединения пустых строк с более короткой случайной строкой, используемой в качестве разделителя).
- Вырезать ровно N символов из строки.
Дальнейшие мысли:
- Это решение не использует заглавные буквы, но почти во всех случаях (без каламбура) это не имеет значения.
- Максимальная длина строки при N = 16 в исходном ответе измеряется в Chrome. В Firefox это N = 11. Но, как было объяснено, второе решение заключается в поддержке любой запрашиваемой длины строки, а не в добавлении случайности, поэтому это не имеет большого значения.
- Все возвращаемые строки имеют одинаковую вероятность возврата, по крайней мере, если результаты, возвращаемые Math.random (), распределены равномерно (в любом случае это не случайность с криптографической стойкостью).
- Не все возможные строки размера N могут быть возвращены. Во втором решении это очевидно (поскольку строка меньшего размера просто дублируется), но и в исходном ответе это верно, поскольку при преобразовании в base-36 последние несколько битов могут не быть частью исходных случайных битов. В частности, если вы посмотрите на результат Math.random (). ToString (36), вы заметите, что последний символ распределен неравномерно. Опять же, почти во всех случаях это не имеет значения, но мы нарезаем последнюю строку с начала, а не с конца случайной строки, чтобы не затрагивать короткие строки (например, N = 1).
Обновление:
Вот пара других однострочников в функциональном стиле, которые я придумал. Они отличаются от решения выше тем, что:
- Они используют явный произвольный алфавит (более общий и подходящий для исходного вопроса, в котором задавались как прописные, так и строчные буквы).
- Все строки длины N имеют одинаковую вероятность возврата (то есть строки не содержат повторений).
- Они основаны на функции карты, а не на приеме toString (36), что делает их более простыми и понятными.
Итак, скажем, ваш алфавит выбора
var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Тогда эти два эквивалента друг другу, так что вы можете выбрать тот, который вам интуитивнее:
Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
и
Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
Edit:
Мне кажется, что кбайт и Мартин де Миллиано придумал решения, аналогичные последним (слава!), Которые я как-то пропустил. Поскольку они не выглядят короткими с первого взгляда, я все равно оставлю их здесь на случай, если кто-то действительно захочет однострочно: -)
Кроме того, во всех решениях заменили «новый массив» на «массив», чтобы сбрить еще несколько байтов.