substring() 메서드의 동작 원리?!

w=j·2021년 5월 9일
0
post-custom-banner

알아보게된 계기

  • 알고리즘 문제를 풀면서 substring() 사용을 하였는데 인자값을 넘길때 정수(예시)2.5)로 넘겨도 정수(예시)2)로 소수점 없이 substring() 메서드가 실행되는것을 봤습니다. 그래서 도대체 어떻게 변환이 되는것일까?! 라는 궁금점 부터 이번 내용을 작성하게 되었습니다.

1.https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/substring 해당 사이트에서 substring() 관련 내용을 살펴 보았습니다.

  • 해당 사이트에 들어가도 substring() 메서드의 동작 방식이 나와있지 않았습니다.

*Specificationa 의 첫번째로 나와있는 문서 "ECMAScript" 문서에 들어가서 확인해 보았습니다.

2. ECMAScript 문서에서 확인

  • 위와 같이 설명이 나왔습니다. 처음 봤을때 도대체 무슨 말인가?! 그래서 구글번역기로 하나하나씩 해석해보기로 했습니다.

3. String.prototype.substring()

The substring method takes two arguments, start and end, and returns a substring of the result of converting this object to a String, starting from index start and running to, but not including, index end of the String (or through the end of the String if end is undefined). The result is a String value, not a String object.

번역 :
"substring" 메소드는 시작과 끝의 두 개의 인수를 사용하고 이 객체를 문자열로 변환한 결과의 하위 문자열을 반환합니다.
인덱스 시작부터 시작하여 실행 대상
문자열의 인덱스 끝(또는 끝이 정의되지 않은 경우 문자열의 끝) 포함하지 않는다.
결과는 "String 객체"가 아닌 String 값이 됩니다.

해석 :
-. substring 메서드는 시작과 끝의 두 개의 인수를 사용한다.

var str = "kong";
str.substring(1, 2);

-. 실행 대상은 인덱스 시작부터 문자열 인덱스 끝(또는 문장열의 끝이 정의되지 않는 경우)는 포함되지 않는다.

var str = "kong";
str.substring(1, 2);
결과 : "o"
  • 문자열 인덱스 끝은 포함되지 않는다.?!
    예시)
    var str = "kong";
    // { 0:k, 1:o, 2:n, 3:g } 해당 인덱스의 각 값이 할당되어있다.
    str.substring(1,2);
    // 1:o 이고 2:n 입니다.
    결과 : "o"로 나온이유는
    실행대상 : index 1 ~ 2 까지 ("on")
    여기서 문자열 인덱스 끝은 포함되지 않는다. 그럼
    "on"에서 문자열 인덱스 끝("n")이 포함되지 않고,
    "o"이 나오게된다.

If either argument is NaN or negative, it is replaced with zero; if either argument is larger than the length of the String, it is replaced with the length of the String.

If start is larger than end, they are swapped.

해석 :
NaN 또는 음수 인수는 0으로 대체되고, 어느 인수가 문자열의 길이보다 크면 문자열의 길이로 대체됩니다.

var str = "kong";
str.substring(1,7);
// 두번째 인자인 7이 문자열 길이(4)보다 크므로 7은 4로 대체된다. 
// 그래서 substring(1,4)로 해석을 하여서
// 결과 : "ong"가 나온다.

시작이 끝보다 크면 서로가 swap(두개의 인자 값이 바뀐다)됩니다.

  • 해당 내용을 위처럼 해석해 보았습니다.
  • 해석은 헷갈리는 부분은 코드작성을통해 보여드렸습니다.
  • 나머지 해석은 부분은 아래에 단계별로 진행 방식을 통해 알아보겠습니다.
  • 그리고 이제 단계별로 설명이 나오는 구문을 알아보겠습니다.
  • 아래 해석부터는 영어가 번역이되어서 말이 매끄럽지 않는 부분은 저의 생각으로 문맥상 맞는 단어로 교체하여 내용을 적어보았습니다.
  • 해당 단계별 설명을 하기전에
    각 단계의 O, S, len, intStart, intEnd, star, end, finalStart, finalEnd, from, to 를 변수로 해석하겠습니다.
    ex)
var O, S, len, intStart, intEnd, star, end, finalStart, finalEnd, from, to; 

The following steps are taken:
1. Let O be ? RequireObjectCoercible(this value).
2. Let S be ? ToString(O).
3. Let len be the length of S.
4. Let intStart be ? ToIntegerOrInfinity(start).
5. If end is undefined, let intEnd be len; else let intEnd be ? ToIntegerOrInfinity(end).
6. Let finalStart be the result of clamping intStart between 0 and len.
7. Let finalEnd be the result of clamping intEnd between 0 and len.
8. Let from be min(finalStart, finalEnd).
9. Let to be max(finalStart, finalEnd).
10. Return the substring of S from from to to.

1) Let O be ? RequireObjectCoercible(this value).

  • Let O be? : 객체 만들기?
  • RequireObjectCoercible(this value) 이건 뭐지?!...

The abstract operation RequireObjectCoercible takes argument argument. It throws an error if argument is a value that cannot be converted to an Object using ToObject.

해석:
추상 연산 RequireObjectCoercible은 인수를 사용합니다. 인수가 ToObject를 사용하여 Object로 변환 할 수없는 값이면 오류가 발생합니다.

  • 여기서 ToObject는 객체가 아닌것을 객체로 만드는 역활을 한다.
    어!! 그럼 설마 이게 오토박싱 과정의 포함이 되어있는 과정인건가?!
    나의 생각으로 오토박싱 과정중의 하나의 과정이라고 생각이 든다..
    아닌가.. ㅎㅎㅎ
  • argument 타입별로 만들어질 객체 타입이 정해지고 객체가 만들어 질수 없으면 오류를 발생시킨다.

* 변수 O : 객체를 생성하여 할당.
* 정리 : 해당 단계는 substring() 메서드를 사용하는 어떤 값을 객체로 만드는 과정이다, 만약 객체로 만들어지지 않는다면 오류를 반환한다.

var str = "kong";
str.substring(1,2);
// 이때 변수 str은 객체가 아니라 원시 값이기때문에 객체로 변환한다.

2) Let S be ? ToString(O).

  • String 객체 만들기?
  • ToString(o)
    이전 단계에서 만든 객체를 다시 String(객체)타입 객체로 만든다

    근데 여기서 이전단계에서 객체로 만들때 substring() 메서드는 String 타입만 사용이 가능해서 이전 단계에서 객체를 생서할때 String 타입으로 객체가 만들어졌을텐데...
    굳이 다시 ToString() 이용하여 String 객체로 다시 만들 필요가 있을까??... 이 궁금즘은 아직은 모르겠다..
    음.. 내 생각은 자바스크립트에서 오류를 발생시키지 않으려고 한번 수행하는 단계라고 생각했다.

  • 변수 S : 이전단계에서 변수 O를 String(객체) 타입으로 생성하여 할당.
    * 정리 : 이전 단계에서 만든 객체를 String(객체) 타입으로 생성한다.

3) Let len be the length of S.

  • "S"(String(객체))의 즉, 문자열의 길이를 len이라 한다.

* 변수 len : 이전 단계에서 변수 S(String)의 문자열 길이(length)를 할당.
* 정리 : String 객체로 만들어진 문자열의 길이를 "len"에 저장.

4) Let intStart be ? ToIntegerOrInfinity(start).

  • ToIntegerOrInfinity(start)
  • ToIntegetOrInfinity(argument)
  • 해석 : 인수를 정수, + ∞ 또는 -∞로 변환하고 변환된 값을 반환한다.
  • 이때 과정중에서 1.Let number be ? ToNumber(argument).
  • ToNumber를 이용하여 Number(객체) 만든다.
    1. Let integer be floor(abs(ℝ(number))).
      해당 과정은 만들어진 Number(객체)의 소수점을 없앤다.
      어떻게?! floor() 통해서
      floor(x) = x - (x modulo 1).(해당 연산을 통해서)
      modulo : 나머지 연산
      ex) floor(2.5) = 2.5 - (2.5를 1로 나누었을때 나머지는 0.5)
      floor(2.5) = 2.5 - 0.5
      floor(2.5) = 2 라는 값이 나온다

*변수 intStart : substring(start,end)의 첫번째 인자 start를 Number(객체)타입으로 생성하여 할당.

* 정리 : 해당 단계는 substring(start,end)의 첫번째 인자인 start를 Number(객체)로 만들고 해당 객체를 만들때 소수점을 없앤다.

5) If end is undefined, let intEnd be len; else let intEnd be ? ToIntegerOrInfinity(end).

  • ToIntegerOrInfinity(end)(이전 단계인 4번 step참조)를 사용하여 Number(객체)로 생성.

* 변수 intEnd : substring(start, end)의 두번째 인자인 end가 정의되지 않았다면 변수 len(문자열길이인 length) 할당.
end가 정의되어 있다면 Number(객체)타입으로 생성하여 할당.

* 정리 : 해당 단계는 substring(start, end)의 두번째 end를 Number(객체)타입으로 생성하고 해당 객체를 만들때 소수점을 없앤다.

6) Let finalStart be the result of clamping intStart between 0 and len.

  • 변수 finalStart에는 변수 intStart를 0 과 변수 len 사이에서 클램핑한결과를 할당한다.
  • 클램핑(clamping) : 어떠한 값(x)를 해당 범위를 기준으로 가장 낮은 값보다 낮으면 하한값으로 반환, 가장 높은값보다 높으면 상한값으로 반환한다. 그리고 x(값)이 범위 사이에 있다면 x(값)을 반환한다.
    ex)
    -. 값(x)가 -1이라고 하면 해당 범위 기준은 0 ~ 4라고 한다 그러면 x(-1)은 가장 낮은 값인 "0"보다 낮으므로 하한값인 "0"을 반납.
    -. 값(x)가 5라고하면 x(5)는 가장 높은값 4보다 높으므로 상한값 4를 반환.
    -. 값(x)가 3이라고 하면 x(3)은 범위 0 ~ 4 사이에 있으므로 x(3)을 반환.

* 변수 finalStart : 변수 intStart(Number)를 해당 0 과 len(문자열 길이) 범위 기준으로 클램핑하여 해당 반환되는 값을 할당.

* 정리 : 해당 단계에서 substring(intStart, indEnd)의 첫번째 인자 변수 intStart 값이 0보다 작으면, 즉 음수이면 0을 할당.
문자열의 길이보다 크면 문자열 길이(length)를 할당.

7) Let finalEnd be the result of clamping intEnd between 0 and len.

  • 변수 finalEnd에는 변수 intEnd를 0과 변수 len 사이에서 클램핑한 결과를 할당한다.
  • 클램핑은 이전 단계 설명과 동일.

*변수 finalEnd : 변수 intEnd(Number)를 해당 0 과 len(문자열 길이) 범위 기준으로 클램핑하여 해당 반환되는 값을 할당.

*정리 : 해당 단계에서 substring(intStart, indEnd)의 두번째 인자 변수 intEnd 값이 0보다 작으면, 즉 음수이면 0을 할당.
문자열의 길이보다 크면 문자열 길이(length)를 할당.

8) Let from be min(finalStart, finalEnd).

  • 변수 from에 min(finalStart,finalEnd) 메서드를 실행하여 반환값을 할당.
  • min(x,y) : argument(인자)값 중에서 가장 작은 값을 반환.

*변수 from : substring(finalStart, finalEnd)의 첫번째 두번째 인자 값을 비교하여 작은값은 변수 from 할당.

*정리 : 해당 단계에서는 substring(from, y)메서드에서 argument(인자 ) 두개를 비교하여 가장작은값을 첫번째 인자(from)에 할당한다.

9) Let to be max(finalStart, finalEnd).

  • 변수 to에 min(finalStart,finalEnd) 메서드를 실행하여 반환값을 할당.
  • max(x,y) : argument(인자)값 중에서 가장 큰 값을 반환.

*변수 to : substring(finalStart, finalEnd)의 첫번째 두번째 인자 값을 비교하여 큰 값은 변수 to 할당.**

*정리 : 해당 단계에서는 substring(from, to)메서드에서 argument(인자) 두개를 비교하여 가장 큰 값을 두번째 인자(to)에 할당한다.

10) Return the substring of S from from to to.

  • 해당 문자열의 from(index) ~ to(index) 사이의 문자열을 반환한다.

총 정리 (예시 코드를통해 정리해보자.)

var str = "kong";
str.substring(5.5,-1);

1) 변수 str("kong")를 객체로 생성.(변수 타입이 문자열이기 때문에 객체는 String 타입으로 생성)

2) 이전 단계에서 생성한 객체를 String 객체로 생성.

3) 생성한 String 타입 객체의 문자열("kong")길이를(length) 저장(어디에 저장 되는건지는 모르겠다. ECMA Script에서는 len이라는 곳에 저장한다고 나와있다.)

4) str.substring(5.5,-1)의 첫번째 인자값인 5.5를 Number(객체)타입으로 생성, 해당 객체로 생성될때는 소수점이 없어진다.
반환되는 결과로는 str.substring(5,-1) 형태로 될것이다.

5) str.substring(5,-1)의 두번째 인자값이 없을 경우엔 3)단계에서 저장한 문자열 길이가 할당된다.
ex) str.substring(5) 일때 두번째 인자에 문자열 할당.
그리고 두번째 인자값인 1을 4)단계 동일한 방법으로 Nunber(객체)타입으로 생성.

6) str.substring(5,-1)의 첫번째 인자 값이 0~4(문자열 길이/length) 기준으로 5는 가장 높은 값(4)보다 크므로 해당 범위에 상한값인 4를 할당
반환되는 결과를 바탕으로 substring(4,-1) 형태로 될것이다.

7) str.substring(4,-1)의 두번째 0~4(문자열 길이/length) 기준으로 -1는 가장 낮은 값(0)보다 작으므로 해당 범위에 하한값인 0을 할당
반환되는 결과를 바탕으로 substring(4,0) 형태로 될것이다.

8) str.substring(4,0)의 첫번째 두번째 인자 값을 비교하여 작은 값첫번째 인자값으로 할당.
9) str.substring(4,0)의 첫번째 두번째 인자 값을 비교하여 큰 값두번째 인자값으로 할당.
반환되는 결과를 바탕으로 substring(0,4) 형태로 될것이다.

10) substring(0,4)를 이용하여 문자열의 index 0,1,2,3 (0~4)

string
0 : "k",
1 : "o",
2 : "n",
3 : "g"

해당 string 객체의 index인 0,1,2,3이 반환되어
결과로는 "kong"가 반환된다.

str.substring(5.5,-1);
결과 : "kong"

** 문제 있는 부분은 언제든지 지적 부탁드립니다.

참조 사이트 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/substring

https://tc39.es/ecma262/#sec-string.prototype.substring

profile
ENJOY!! PROGRAMING!!
post-custom-banner

0개의 댓글