파트 1 - 4) 자료구조와 자료형 - 1) 원시값의 메서드

Lee·2021년 10월 24일
0


원시값의 메서드 파트 링크 : https://ko.javascript.info/primitives-methods

원시값은 객체가 아니다!!
당연히 아니라고 생각하지만 둘의 차이점에 대해서 다루고 있다.

원시값은 원시형 값이고 그 종류로는 문자(string), 숫자(number), bigint, 불린(boolean), 심볼(symbol), null, undefined형으로 총 일곱 가지가 있다.

객체는 프로퍼티에 다양한 종류의 값을 저장할 수 있고 중괄호 {}를 사용하여 만들 수 있다. 자바스크립트에는 여러 종류의 객체가 있는데 함수도 객체의 일종이다.
객체는 함수도 프로퍼티로 저장할 수 있다.

자바스크립트는 날짜, 오류, HTML 요소(HTML element) 등을 다룰 수 있게 해주는 다양한 내장 객체를 제공하고 이 객체들은 고유한 프로퍼티와 메서드를 가진다.

하지만, 객체는 원시값보다 “무겁고”, 내부 구조를 유지하기 위해 추가 자원을 사용하기 때문에 이런 기능을 사용하면 시스템 자원이 많이 소모된다는 단점이 있다.


원시값을 객체처럼 사용하기

자바스크립트 창안자는 문자열이나 숫자와 같은 원시값을 다룰 일이 많은데 이 때 메서드를 사용하면 작업을 수월하게 할 수 있을 것 같지만 원시값은 가능한 한 빠르고 가벼워야 한다는 고민이 있었다.

따라서 원시값은 원시값 그대로 단일 값 형태를 유지하고 문자열, 숫자, 불린, 심볼이 가진 고유 메서드와 프로퍼티에 접근할 수 있도록 언어 차원에서 허용했다.
위처럼 각 원시값이 원시값의 고유 메서드, 프로퍼티에 접근하기 위해서는 추가 기능을 제공해주는 특수한 객체, "원시 래퍼 객체(object wrapper)"를 만든다. 이 객체는 곧 삭제된다.

원시 래퍼 객체는 우리가 흔히 보던 String,Number,Boolean, Symbol이다. 이 래퍼 객체마다 제공하는 메서드들도 각각 다르다. 자꾸 당연한 이야기를 적고 있는 것 같다...

예시로 원시값 string이 가지는 프로퍼티이자 원시 래퍼 객체 String이 가지는 메서드 toUpperCase()를 살펴보자.

<script>
  let str = "Hello";

  alert( str.toUpperCase() ); // HELLO
</script>

str.toUpperCase() 메서드를 호출하면 아래와 같은 과정이 진행된다.

  1. 문자열 str은 원시값이므로 원시값의 프로퍼티(toUpperCase)에 접근하는 순간 특별한 객체(String)가 만들어진다. 이 객체는 문자열의 값을 알고 있고, toUpperCase()와 같은 유용한 메서드를 가지고 있다.
  2. 메서드(toUpperCase)가 실행되고, 새로운 문자열이 반환된다(alert 창에 이 문자열이 출력된다).
  3. 특별한 객체(String)는 파괴되고, 메스드를 통해 변환된 원시값 str만 남는다.

요약하면 원시값의 프로퍼티인 메서드(toUpperCase)에 접근 => 실제 toUpperCase 메서드를 가진 래퍼객체인 String 객체가 생성되어 toUpperCase를 실행 => 메서드 실행이 완료되면 String 객체는 사라지고 원시값인 str 만 남는 과정으로 보인다.

자바스크립트 엔진은 프로세스 최적화에 많은 신경을 써 실제로 원시 래퍼 객체를 만들지 않고도 위처럼 원시 래퍼 객체를 생성한 것처럼 동작하게 해준다.

위에서 본 문자형의 고유메서드 뿐만 아니라 숫자형도 고유메서드가 있다.
숫자형의 고유메서드 toFixed(n)을 사용하면 원하는 자리에서 소수점 아래 숫자를 반올림 할 수 있다.

<script>
  let n = 1.23456;

  alert( n.toFixed(2) ); // 1.23
</script>

이런 원시 래퍼 객체들은 그냥 사용하면 나중엔 객체는 사라져서 원시값만 반환하여 원하는 결과를 얻을 수 있는데 new 생성자와 함께 사용하면 객체를 반환해 문제가 생긴다.
예를들어 new Number("123")을 alert 함수에 사용하면 alert 함수는 객체도 string 으로 변환하여 에러는 발생하지 않지만 [object Object]를 뱉는다.
new 생성자가 객체를 반환하기 때문이다!
이렇게 되면 출력값이 잘못됐다는 걸 알아차릴수라도 있는데 만약 조건문에 저 조건을(객체값을) 참으로 둔다면? 객체는 논리 평가시 항상 true를 반환하기 때문에 맞지 않다.

<script>
  let zero = new Number(0);

  if (zero) { // 변수 zero는 객체이므로, 조건문이 참이 됩니다.
    alert( "그런데 여러분은 zero가 참이라는 것에 동의하시나요!?!" );
  }
  // 동의하지 않는다. zero는 객체고 객체는 논리 평가시 항상 true를 반환하니까!!
</script>
  • null과 undefined 에는 메서드가 없다.
    이 둘도 원시값이지만 이 둘은 메서드가 없다. 물론 래퍼객체도 없다. 이런 면에서는 이 둘이 원시값들 중 가장 원시적이라고 볼 수 있다.

래퍼객체를 수정할 수 있는가?

엄격 모드에서는 안되고 비엄격 모드에서는 된다.

<script>
  let str = "Hello";

  str.test = 5;

  alert(str.test);
</script>

비 엄격 모드에서는 래퍼 객체 수정이 가능하여 str.test 실행 => String 객체 생성후 그 객체에 test라는 프로퍼티를 추가 => 하지만 이 String 객체는 동작 후 사라져서 test라는 프로퍼티를 찾지 못해 undefined를 반환한다.

엄격 모드에서는 래퍼 객체 수정이 불가능하여 에러를 반환한다.

profile
하고 싶은 게 너무 많습니다.

0개의 댓글

관련 채용 정보