Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why javascript's charAt() with a string returns the first letter

Tags:

javascript

I am doing some exercises in my object-oriented javascript book, I notice that this:

var a = "hello";
a.charAt('e'); // 'h'
a.charAt('adfadf'); //'h'

Why is the string in the argument seemingly evaluated to the integer 0 for the charAt() method for strings?

Edit: I was aware that the charAt()'s usage usually takes an integer, and the exercise feeds charAt() with a string, and I also was aware that the string is likely then to be coerced into an integer first, which I did verify to be NaN. Thanks Kendall, for suggesting putting this missing bit of information in the question proper

Thanks!

like image 951
Nik So Avatar asked Apr 02 '12 17:04

Nik So


People also ask

Does charAt return character or string?

The charAt() method returns the character at the specified index in a string.

Can charAt return a string?

Return valueIf index is out of range, charAt() returns an empty string.

What is the correct function to return the first character in a string?

LEFT returns the first character or characters in a text string, based on the number of characters you specify.

What is the return type of charAt ()?

The Java String class charAt() method returns a char value at the given index number. The index number starts from 0 and goes to n-1, where n is the length of the string. It returns StringIndexOutOfBoundsException, if the given index number is greater than or equal to this string length or a negative number.


2 Answers

Because Number('e') is NaN, and <any nonempty string>.charAt(NaN) just returns the first character. This behavior is exactly what is laid out in the spec:

15.5.4.4 String.prototype.charAt (pos)

When the charAt method is called with one argument pos, the following steps are taken:

  1. Call CheckObjectCoercible passing the this value as its argument.
  2. Let S be the result of calling ToString, giving it the this value as its argument.
  3. Let position be ToInteger(pos).
  4. Let size be the number of characters in S.
  5. If position < 0 or position ≥ size, return the empty String.
  6. Return a String of length 1, containing one character from S, namely the character at position position, where the first (leftmost) character in S is considered to be at position 0, the next one at position 1, and so on.

Step 3 is the crux of the matter. ToInteger of both 'e' and 'adfadf' is 0. Why? Again, time to hit the spec:

9.4 ToInteger

The abstract operation ToInteger converts its argument to an integral numeric value. This abstract operation functions as follows:

  1. Let number be the result of calling ToNumber on the input argument.
  2. If number is NaN, return +0.
  3. If number is +0, -0, +∞, or −∞, return number.
  4. Return the result of computing sign(number) × floor(abs(number)).

We need to go deeper! What is ToNumber('e'), and what is ToNumber('adfadf')? If you're surprised that I'm once again about to quote the spec, I'm doing something wrong:

9.3.1 ToNumber Applied to the String Type

ToNumber applied to Strings applies the following grammar to the input String. If the grammar cannot interpret the String as an expansion of StringNumericLiteral, then the result of ToNumber is NaN.

...I'm not going to quote the entire grammar for StringNumericLiteral. Because 'e' and 'adfadf' are neither StrDecimalLiteral s nor HexIntegerLiteral s, ToNumber of both of those values is NaN. Finally we have the conversion: from string to NaN to 0, which brings us back up the chain to charAt: position is 0, so charAt('e') and charAt('adfadf') both return the leftmost character in S.

Now, if those strings were instead valid StrNumericLiteral s, such as '0xe' and '0xadfadf':

> 'hello'.charAt('0xe')
  ""
> 'hello'.charAt('0xadfadf')
  ""

well, that's a different story for a different answer.

like image 118
Matt Ball Avatar answered Nov 04 '22 19:11

Matt Ball


The JavaScript core string.charAt(idx) method takes an integer argument as the index for which character to return.

'abc'.charAt(0); // => 'a'

If you give it a non-integer argument then it will presumably attempt to convert the argument to a number using either the Number(arg) converter or possibly parseInt(arg, 10). Both of these functions return NaN if given a string that doesn't parse as an integer, so the charAt() function must convert NaN to zero automatically:

Number('e'); // => NaN
parseInt('e', 10); // => NaN
'abc'.charAt(NaN); // => 'a'

Perhaps directly related, calling charAt() with no argument returns the first character:

'abc'.charAt(); // => 'a'
like image 30
maerics Avatar answered Nov 04 '22 21:11

maerics