string[x]과 string.charAt(x)은 어떻게 다른가? 'hello'[NaN] 과 'hello'.charAt(NaN) 은 같은가?

Maria Kim·2023년 4월 22일
0

알고리즘은 풀던 중 string.charAt(x)string[x]은 어떻게 다른가에 대해 고민하다.

위 두 글을 보고 charAt과 string[]의 작동법에 대해 찾아보게 되었다.
그 후 1번째 글에서 봤던 아래 코드 결과가 나온 과정을 정리해보기로 했다.

과정을 확인할 코드

'hello'[NaN] 
'hello'.charAt(NaN)

string의 [] & charAt(x) 스펙

string의 [] spec


15.5.5.2 [GetOwnProperty] # Ⓣ Ⓔ
String objects use a variation of the [[GetOwnProperty]] internal method used for other native ECMAScript objects (8.12.1). This special internal method is used to add access for named properties corresponding to individual characters of String objects.

Assume S is a String object and P is a String.

When the [[GetOwnProperty]] internal method of S is called with property name P, the following steps are taken:

  1. Let desc be the result of calling the default [[GetOwnProperty]] internal method (8.12.1) on S with argument P.

  2. If desc is not undefined return desc.

  3. If ToString(abs(ToInteger(P))) is not the same value as P, return undefined.

  4. Let str be the String value of the [[PrimitiveValue]] internal property of S.

  5. Let index be ToInteger(P).

  6. Let len be the number of characters in str.

If len ≤ index, return undefined.

Let resultStr be a String of length 1, containing one character from str, specifically the character at position index, where the first (leftmost) character in str is considered to be at position 0, the next one at position 1, and so on.

Return a Property Descriptor { [[Value]]: resultStr, [[Enumerable]]: true, [[Writable]]: false, [[Configurable]]: false }


charAt(x) spec


15.5.4.4 String.prototype.charAt (pos) # Ⓣ Ⓡ
Returns a String containing the character at position pos in the String resulting from converting this object to a String. If there is no character at that position, the result is the empty String. The result is a String value, not a String object.

If pos is a value of Number type that is an integer, then the result of x.charAt( pos) is equal to the result of x.substring( pos, pos+1).

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.

NOTE The charAt function is intentionally generic; it does not require that its this value be a String object. Therefore, it can be transferred to other kinds of objects for use as a method.


과정을 유추해보자

NaN 어떤 변화를 거치며 결과를 만들까?

'hello'[NaN] 
'hello'.charAt(NaN)

string의 [] - 'hello'[NaN] 과정 유추해보기

  • P는 String 이고 넣은 파라미터라고 정의

string의 [] 스펙 15.5.5.2 [GetOwnProperty]의 3번을 그럼 확인해 보면 될 것이다.

If ToString(abs(ToInteger(P))) is not the same value as P, return undefined.
위 3번 내용은 다시 아래 내용으로 분리해서 생각해보자.

3-1 ToInteger(P)

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)).


  • 3-1-1에서 ToNumber을 호출한다.
    - 아래 ToNumber 의 스펙을 보면 type이 number 이기 때문에
    NaN -> NaN로 반환

ToNumber 스펙


  • 3-1-2번에서 NaN 이면
    +0을 반환

∴ 3-1 결과 값 +0

3-2 abs(ToInteger(P))


abs() 스펙

Returns the absolute value of x; the result has the same magnitude as x but has positive sign.

  • If x is NaN, the result is NaN.
  • If x is −0, the result is +0.
  • If x is −∞, the result is +∞.

3-1 의 값이 +0 이였기 때문에 그대로 +0 반환
∴ 3-2 결과 값 +0

3-3 ToString(abs(ToInteger(P)))


ToString() 스펙

9.8.1.


type 이 number이니 Number 에서 보라고 하는 9.8.1을 확인해보면
9.8.1-2번에서 +0 은 "0"로 변환됨을 확인할 수 있다.

∴ 3-3 결과 값 '0'

3-4 ToString(abs(ToInteger(P)))와 P 비교

드디어 비교하기

  • ToString(abs(ToInteger(P))) : '0'
  • P : NaN

'0' 과 NaN 의 값은 같은가? -> false

결과

undefined

charAt() - 'hello'.charAt(NaN) 과정 유추해보기

2. ToString()

스펙의 2번부터 확인해보자
2. Let S be the result of calling ToString, giving it the this value as its argument.


ToString() 스펙


'hello'은 이미 type String 임으로

∴ S = 'hello'

3. ToInteger(pos)


ToInteger(pos) 스펙

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)).


ToNumber 스펙


3. Let position be ToInteger(pos).

  • 3에서 ToInteger을 호출

  • ToInteger(pos)의 1번에서 ToNumber를 호출
    ToNumber 의 스펙을 보면 type이 number 이기 때문에
    NaN -> NaN 반환

  • ToInteger(pos)의 2번에서 NaN 은 +0을 반환
    NaN -> 0+ 반환

∴ position = 0+

4. size 정의

Let size be the number of characters in S.
hello의 size 는 5

size = 5

5. postion 유효성 검사

5. If position < 0 or position ≥ size, return the empty String.
0 은 유효함으로 넘어감

6. postion에 해당하는 문자 반환하기

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.

hello의 0번째 문자는 'h'임으로

결과

'h' 반환

생각해보기

아래의 코드도 생각해보기

'hello'[true] 
'hello'.charAt(true) 
console.log('hello'['a']) // console에 찍힐 값은?
'hello'['a'] = 'aaa'
console.log('hello'['a']) // console에 찍힐 값은?
profile
Frontend Developer, who has business in mind.

0개의 댓글