2021-09-18

JSでA〜Zまでのランダムな文字列を生成する

とあるところで、以下のコードでA〜Zまでの範囲でランダムな文字を1つ返す方法があった

String.fromCharCode(65 + Math.floor(Math.random() * 26))

何をやっているのかみていく

まず Math.random() は 0以上1未満のランダムな不動小数を返す
それに26をかけているのは、 String.fromCharCode を見ていくと理解できるので後で説明するとして
とにかく Math.random() * 26 の時点では

0.000001 * 26 = 0.000026
0.999999 * 26 = 25.999973999999998

雑だけど小さい方と大きい方でこのくらいの数値が生成されていて
Math.floor によって小数点以下切り捨てられ、0〜25の値を取得していることがわかる

次に65を加算しているが、これまた String.fromCharCode を見ると理解できるので働きをみていく

String.fromCharCode は指定されたUTF-16コードユニットの並びから生成された文字列を返すというもの
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode

String.fromCharCode の引数である 65 + Math.floor(Math.random() * 26) が生成する整数は、上で書いた通り 65〜90 までのランダムな値となる

この65〜90というのはUTF16コードユニット的に 0x0041〜0x005A を示すので
最終的に A〜Z のいずれかの文字列を返していることがわかる
http://itdoc.hitachi.co.jp/manuals/3020/30203N73A0/NTSO0551.HTM

これでA〜Zの間で1つのランダムな文字列が得られるので、何文字かのランダムな文字列が欲しい場合は
[… new Array(3)].map(num => String.fromCharCode(65 + Math.floor(Math.random() * 26)))
みたいにすれば欲しい文字数のランダムな文字列が得られる(↑の例は3文字)

記号なども範囲を変えれば同じ方法で生成できるが
「A〜Zまたはa〜z」みたいな範囲にしたい場合は、間に不要な記号などが含まれてしまうため、ちょっと工夫が必要

なるほどなぁ〜