604

I would like to alert each letter of a string, but I am unsure how to do this.

So, if I have:

var str = 'This is my string';

I would like to be able to separately alert T, h, i, s, etc. This is just the beginning of an idea that I am working on, but I need to know how to process each letter separately.

I was thinking I might need to use the split function after testing what the length of the string is.

How can I do this?

1
  • 11
    Maybe you were looking for this: as of ES6, there is for(const c of str) { ... }. More of that further below in a quite detailed but not sufficiently upvoted answer. PS: @ARJUN's link doesn't work for me. Commented Jan 27, 2019 at 16:03

24 Answers 24

648

If the order of alerts matters, use this:

for (let i = 0; i < str.length; i++) {
  alert(str.charAt(i));
}

Or this: (see also this answer)

 for (let i = 0; i < str.length; i++) {
   alert(str[i]);
 }

If the order of alerts doesn't matter, use this:

let i = str.length;
while (i--) {
  alert(str.charAt(i));
}

Or this: (see also this answer)

let i = str.length;
while (i--) {
  alert(str[i]);
}

var str = 'This is my string';

function matters() {
  for (let i = 0; i < str.length; i++) {
    alert(str.charAt(i));
  }
}

function dontmatter() {
  let i = str.length;
  while (i--) {
    alert(str.charAt(i));
  }
}
<p>If the order of alerts matters, use <a href="#" onclick="matters()">this</a>.</p>

<p>If the order of alerts doesn't matter, use <a href="#" onclick="dontmatter()">this</a>.</p>

Sign up to request clarification or add additional context in comments.

13 Comments

using the [] to get the char in a specific position isn't supported in IE < 9
as covered in the other answer, you could use str.charAt(i) in place of the []'s. for more on why you should use charAt vs [], see string.charAt(x) or string[x]
I find it hard to believe any modern JS compiler would re-calculate the length if the string hasn't been modified inside the loop. In every other language I'd happily do the length check in the test clause of the for loop, assuming the compiler knows best and would optimise it accordingly.
@Dagmar: Javascript does not use UTF-8, it uses UTF-16 (or UCS-2, depending on the browser). Every single character can be represented as either UTF-8 or UTF-16 but not have this problem. The only ones that have the problem are the ones that require four bytes in UTF-16 rather than two bytes. 💩 is a character that requires four bytes in UTF-16. Key terms to look up for more info are "astral plane", "non-BMP", and "surrogate pair".
@Dagmar: Java and Javascript both have UTF-16 (formerly UCS-) in common. The third major platform that uses it is Windows. Unix, MacOS, and internet protocols use UTF-8. charAt is left over from the UCS-2 days when there were no surrogate pairs and to address the problem a new function, codepointAt was added to JavaScript that handles our friendly pile of poo correctly. I believe Java also has it.
|
476

It's probably more than solved. Just want to contribute with another simple solution:

var text = 'uololooo';

// With ES6
[...text].forEach(c => console.log(c))

// With the `of` operator
for (const c of text) {
    console.log(c)
}

// With ES5
for (var x = 0, c=''; c = text.charAt(x); x++) { 
    console.log(c); 
}

// ES5 without the for loop:
text.split('').forEach(function(c) {
    console.log(c);
});

11 Comments

the last example can simply be [...text].forEach(console.log)
Nope, it can't. forEach() passes the index and the array as second and third argument. I would rather not log that..
Note that both the spread operator (first example) and the split call (last example) will create a new array. This won't usually be a problem, but could be costly for large strings or frequent uses.
What about for (let c of [...text]) { console.log(c) }
Of these, only the first two will iterate through the characters of the string. The rest iterate though the UTF-16 code units. For example try text = "\ud835\udcaf\ud835\udcae\ud835\udca9" This string has 3 unicode characters in it, but 6 code-units.
|
127

How to process each letter of text (with benchmarks)

https://jsperf.com/str-for-in-of-foreach-map-2

for

Classic and by far the one with the most performance. You should go with this one if you are planning to use it in a performance critical algorithm, or that it requires the maximum compatibility with browser versions.

var str = "Hello";
for (var i = 0; i < str.length; i++) {
  console.info(str[i]);
}

for...of

for...of is the new ES6 for iterator. Supported by most modern browsers. It is visually more appealing and is less prone to typing mistakes. If you are going for this one in a production application, you should be probably using a transpiler like Babel.

let result = '';
for (let letter of str) {
  result += letter;
}

forEach

Functional approach. Airbnb approved. The biggest downside of doing it this way is the split(), that creates a new array to store each individual letter of the string.

Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side effects.

// ES6 version.
let result = '';
str.split('').forEach(letter => {
  result += letter;
});

or

var result = '';
str.split('').forEach(function(letter) {
  result += letter;
});

The following are the ones I dislike.

for...in

Unlike for...of, you get the letter index instead of the letter. It performs pretty badly.

var result = '';
for (var letterIndex in str) {
  result += str[letterIndex];
}

map

Function approach, which is good. However, map isn't meant to be used for that. It should be used when needing to change the values inside an array, which is not the case.

// ES6 version.
var result = '';
str.split('').map(letter => {
  result += letter;
});

or

let result = '';
str.split('').map(function(letter) {
  result += letter;
});

7 Comments

On my machine the classic for loop was actually the second slowest, while for...of was the fastest (about three times as fast as for).
Where is the benchmark? What's the fastest solution?
@johnywhy That was two years ago and the link is dead so I'm not sure how you expect me to defend the result I got back then. Setting up a new benchmark now agrees with zurfyx's conclusion though, with the for loop being slightly faster.
@JohnMontgomery I don't expect you to do anything. Just a note to future readers that your results are different than the answer. I personally would like to know which results apply to browsers today 2020, altho' 2018 wasn't that long ago. Which link is dead?
@johnywhy The link at the top with all the actual tests is returning a 404 for me.
|
77

One possible solution in pure JavaScript:

for (var i = 0; i < str.length; i++)
{
    var char = str.charAt(i);
    alert(char);
}

9 Comments

It would probably be better with var x = 0 and var c = str.charAt(x).
Also, str.length should be stored in a variable so it doesn't have to keep being accessed.
@EliGrey Is it really that important to put length in a variable? Do you have benchmarks when this would be preferable over having fewer lines of code?
@paul_sns Also interestingly, Chrome did the same test in around 2% of the time (~5ms vs ~0.0997ms), and both versions gave the same time, so it looks like Edge isn't optimized.
for (var x = 0, c=''; c = "💩💩💩💩💩💩💩💩".charAt(x); x++) { console.log(c); }
|
63

Most if not all of the answers here are wrong because they will break whenever there is a character in the string outside the Unicode BMP (Basic Multilingual Plane). That means all Emoji will be broken.

JavaScript uses UTF-16 Unicode for all strings. In UTF-16, characters beyond the BMP are made out of two parts, called a "Surrogate Pair" and most of the answers here will process each part of such pairs individually instead of as a single character.

One way in modern JavaScript since at least 2016 is to use the new String iterator. Here's the example (almost) straight out of MDN:

var string = 'A\uD835\uDC68B\uD835\uDC69C\uD835\uDC6A';

for (var v of string) {
  alert(v);
}
// "A"
// "\uD835\uDC68"
// "B"
// "\uD835\uDC69"
// "C"
// "\uD835\uDC6A"

1 Comment

For a modern solution to splitting a string into characters while taking into account surrogate pairs, see: stackoverflow.com/a/42596897/527702
19

You can try this

var arrValues = 'This is my string'.split('');
// Loop over each value in the array.
$.each(arrValues, function (intIndex, objValue) {
    alert(objValue);
})

2 Comments

Still is an option, but not performant. Don't put jQuery everywhere.
Don't use any libraries, unless you really need it.
17

New JS allows this:

const str = 'This is my string';
Array.from(str).forEach(alert);

1 Comment

Best answer! I intuitively tried it and it worked, wanted to post it, then discovered that I'm too late )
15

If you want to do a transformation on the text on a character level, and get the transformed text back at the end, you would do something like this:

var value = "alma";
var new_value = [...value].map((x) => x+"E").join("")

So the steps:

  • Split the string into an array (list) of characters
  • Map each character via a functor
  • Join the resulting array of chars together into the resulting string

NOTE: If you need performance, there are probably better, more optimized solutions for this. I posted this one as a clean codestyle approach.

1 Comment

This is one of the solution, but it is not an optimized solution.
10

One more solution...

var strg= 'This is my string';
for(indx in strg){
  alert(strg[indx]);
}

1 Comment

If you only want the char and not the index, it would be faster to use a for..of loop for (let ch of t) { alert(ch) }
10

It is better to use the for...of statement, if the string contains unicode characters, because of the different byte size.

for(var c of "tree 木") { console.log(c); }
//"𝐀A".length === 3

Comments

10

short answer: Array.from(string) will give you what you probably want and then you can iterate on it or whatever since it's just an array.

ok let's try it with this string: abc|⚫️\n⚪️|👨‍👩‍👧‍👧.

codepoints are:

97
98
99
124
9899, 65039
10
9898, 65039
124
128104, 8205, 128105, 8205, 128103, 8205, 128103

so some characters have one codepoint (byte) and some have two or more, and a newline added for extra testing.

so after testing there are two ways:

  • byte per byte (codepoint per codepoint)
  • character groups (but not the whole family emoji)

string = "abc|⚫️\n⚪️|👨‍👩‍👧‍👧"

console.log({ 'string': string }) // abc|⚫️\n⚪️|👨‍👩‍👧‍👧
console.log({ 'string.length': string.length }) // 21

for (let i = 0; i < string.length; i += 1) {
  console.log({ 'string[i]': string[i] }) // byte per byte
  console.log({ 'string.charAt(i)': string.charAt(i) }) // byte per byte
}

for (let char of string) {
  console.log({ 'for char of string': char }) // character groups
}

for (let char in string) {
  console.log({ 'for char in string': char }) // index of byte per byte
}

string.replace(/./g, (char) => {
  console.log({ 'string.replace(/./g, ...)': char }) // byte per byte
});

string.replace(/[\S\s]/g, (char) => {
  console.log({ 'string.replace(/[\S\s]/g, ...)': char }) // byte per byte
});

[...string].forEach((char) => {
  console.log({ "[...string].forEach": char }) // character groups
})

string.split('').forEach((char) => {
  console.log({ "string.split('').forEach": char }) // byte per byte
})

Array.from(string).forEach((char) => {
  console.log({ "Array.from(string).forEach": char }) // character groups
})

Array.prototype.map.call(string, (char) => {
  console.log({ "Array.prototype.map.call(string, ...)": char }) // byte per byte
})

var regexp = /(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g

string.replace(regexp, (char) => {
  console.log({ 'str.replace(regexp, ...)': char }) // character groups
});

Comments

9

When I need to write short code or a one-liner, I use this "hack":

'Hello World'.replace(/./g, function (char) {
    alert(char);
    return char; // this is optional 
});

This won't count newlines so that can be a good thing or a bad thing. If you which to include newlines, replace: /./ with /[\S\s]/. The other one-liners you may see probably use .split() which has many problems

4 Comments

best answer. Takes into account problems with unicode and also can be used with functional constructs with .map() etc.
Only thing I don't like about this one is when I want access to the extra params passed to the forEach call's function vs the params sent in replace. If I know I'm ASCIIing, I think I still have some use cases for split. Great answer, though!
This answer has the bonus with preselecting the values you would check against anyway
I thought this wouldn't take into account the Unicode problems unless it had the u flag along with the g flag? OK just tested and I was right.
9

You can now use in keyword.

    var s = 'Alien';
    for (var c in s) alert(s[c]);

5 Comments

Using in is bad practice and horrible when unfiltered I strongly advise against this
@Downgoat why? What's bad about it? I mean if I'm in a situation where I know that 'in' is supported by my Javascript engine, and that my code won't find its way into another engine...why not use that?
@TKoL See this.
@Alan in is a legitimate part of the language. Use things appropriately. Your article cautions that in interprets alpha keys same as numeric keys. So? Maybe that's what you want. It could also be said that other methods incorrectly ignore alpha keys. Imo, of has correct behavior. In JS arrays, elements without alpha keys still have keys: numeric ones. In my console, JS "correctly" treats the alpha key same as the numeric keys: >const arr = ['a', 'b'] >arr.test = 'hello' >arr 0: "a" 1: "b" test: "hello" length: 2
There is nothing wrong about the usage of in if you know what data formats you have and in this case we know exactly that we have a string as an array. @johnywhy I totally agree with you.
8

You can now iterate over individual Unicode code points contained in a String by using String.prototype[@@iterator], which returns a value of well known Symbol type Symbol.iterator - the default iterator for array-like Objects (String in this case).

Example code:

const str = 'The quick red 🦊 jumped over the lazy 🐶! 太棒了!';

let iterator = str[Symbol.iterator]();
let theChar = iterator.next();

while(!theChar.done) {
  console.log(theChar.value);
  theChar = iterator.next();
}

// logs every unicode character as expected into the console.

This works with Unicode characters such as emoji or non-roman characters that would trip up legacy constructs.

Reference: MDN Link to String.prototype@@iterator.

1 Comment

Note that you can do this in a shorter manner with a for ... of loop as well over the string - that is syntax sugar for accessing the iterator.
8

You can simply iterate it as in an array:

var txt = "Hello";
for(var i in txt){
    console.log(txt[i]);
}

1 Comment

and nowadays even for (var i of txt) { console.log(i) }
7

In ES6 / ES2015, you can iterate over an string with iterators,as you can see in

Symbol.iterator MDN

var str = 'Hello';
var it = str[Symbol.iterator]();

for (let v of it) {
  console.log(v)
 }
 
//  "H"
//  "e"
//  "l"
//  "l"
//  "o"

It is a declarative style. What is the advantage? You do not have to concern about how to access each element of the string.

Comments

7

// There are multiple ways but I find this easiest.

let str = 'This is my string';
for(let character of str) 
  console.log(character)

Comments

4

You can get an array of the individual characters like so

var test = "test string",
    characters = test.split('');

and then loop using regular Javascript, or else you can iterate over the string's characters using jQuery by

var test = "test string";

$(test.split('')).each(function (index,character) {
    alert(character);
});

Comments

3

you can convert this string into an array of chars using split(), then iterate through it.

const str = "javascript";
const strArray = str.split('');

strArray.map(s => console.log(s));

1 Comment

apparently this fails with unicode characters and graphic symbols.
0

In today's JavaScript you can

Array.prototype.map.call('This is my string', (c) => c+c)

Obviously, c+c represents whatever you want to do with c.

This returns

["TT", "hh", "ii", "ss", " ", "ii", "ss", " ", "mm", "yy", " ", "ss", "tt", "rr", "ii", "nn", "gg"]

1 Comment

Possibly: [...'This is my string'].map((c)=>c+c)
0

This should work in older browsers and with UTF-16 characters like 💩.

This should be the most compatible solution. However, it is less performant than a for loop would be.

I generated the regular expression using regexpu

var str = 'My String 💩 ';
var regEx = /(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g


str.replace(regEx, function (char) {
    console.log(char)
});

Hope this helps!

1 Comment

What do you mean by "less perfomant"? I think you mean "slower" as it is more conformant to the requirement and it performs well.
-1

You can access single characters with str.charAt(index) or str[index]. But the latter way is not part of ECMAScript so you better go with the former one.

2 Comments

I'd stay away from that. Unfortunately that doesn't work in all versions of IE. Trust me. I learned it the hard way.
It is part of ECMAScript, but only in newly-released 5th edition, not 3rd.
-1

If you want to animate each character you might need to wrap it in span element;

var $demoText = $("#demo-text");
$demoText.html( $demoText.html().replace(/./g, "<span>$&amp;</span>").replace(/\s/g, " "));

I think this is the best way to do it, then process the spans. ( for example with TweenMax)

TweenMax.staggerFromTo( $demoText.find("span"), 0.2, {autoAlpha:0}, {autoAlpha:1}, 0.1 );

Comments

-1

Try this code

    function myFunction() {
    var text =(document.getElementById("htext").value); 
    var meow = " <p> <,> </p>";
    var i;


    for (i = 0; i < 9000; i++) {

        text+=text[i] ;



    }

    document.getElementById("demo2").innerHTML = text;

}
</script>
<p>Enter your text: <input type="text" id="htext"/>

    <button onclick="myFunction();">click on me</button>
</p>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.