Square-bracket indexing of code units within a string isn't a "modern alternative" tocharAt, both have been in JS since the beginning. The only difference is square-bracket indexing returnsundefined instead of"" for out-of-bounds indexes.
NeithercharAt nor square-bracket indexing are truly modern alternatives, because neither support non-BMP characters (e.g. most emojis):
'💩'[0]// '\uD83D''💩'.charAt(0)// '\uD83D'
You can make a more modern version that works generically on iterables something like this:
Strings are iterated by codepoint, rather than code-unit, so emojis and other non-BMP characters are handled correctly.
The last example uses segments from anIntl.Segmenter as the iterable, so each "character" is a grapheme cluster (closer to the concept of what users of relevant languages would consider to be a "character"). A grapheme cluster can consist of one or more Unicode codepoints.