회고록 블로그

[공부 필기] JavaScript 문법 공부 23일차 (3) 본문

2. 프로그래밍 언어 공부/JavaScript

[공부 필기] JavaScript 문법 공부 23일차 (3)

김간장 2022. 5. 24. 23:10

※ 필자는 초초초보자입니다.

※ 틀린 내용에 대한 피드백은 언제든지 환영합니다.

 

 

공부하고 있는 자료 : modern JavaScript tutorial 

https://ko.javascript.info/primitives-methods

 

원시값의 메서드

 

ko.javascript.info

 

✅ 원시값의 메서드

- 일단 확실하게 한 가지 정리할 것이 있다.

   "원시값은 객체가 아니다."

- 원시값에도 객체처럼 메서드를 호출할 수 있지만, "원시값은 객체가 아니다"

 

- 원시값 vs 객체

   ► 원시값 : 원시형 값이며 종류로는 [문자 / 숫자 / bigInt / 불린(boolean) / 심볼(symbol) / null / undefined 형](7가지)이 있다.

   ► 객체 : 프로퍼티에 다양한 종류의 값을 저장할 수 있으며, 함수도 객체의 일종이다.

 

- 객체의 장점 중 하나는 메서드를 정의할 수 있다는 것

   ► 자바스크립트는 날짜, HTML 요소 등을 다룰 수 있는 다양한 내장 객체를 제공하며

       이 내장 객체들도 고유한 프로퍼티와 메서드를 갖는다.

   ► 하지만 객체를 많이 사용하는건 시스템 자원이 많이 소모된다는 단점이 있다.

        /* 객체가 원시값보다 무겁고, 내부 구조를 유지하기 위해 추가 자원을 사용하기 때문 */

   

 

✅ 원시값을 객체처럼 사용할 수 있을까

- 자바스크립트 창안자는 이런 생각을 했다고 한다.

   ► 문자열, 숫자 등을 다루는 작업이 많은데, 메서드를 사용하면 작업을 수월하게 할 수 있을 것 같다.

   ► 그렇지만 원시값은 가능한 한 빠르고 가벼워야 한다. (메서드를 사용하기 위해 객체로 만들자니 너무 무겁다)

 

- 그에 대한 해결 방안으로 아래의 내용을 생각해냈다.

   ► 원시값은 원시값 그대로 남겨둬서 단일 값 형태를 유지한다.

   ► 메서드와 프로퍼티에 접근할 수 있도록 언어 차원에서 허용한다. (문자열, 숫자, 불린, 심볼)

 

- 이를 위해서 [원시 래퍼 객체(object wrapper)]를 만들어줬다.

   ► 원시값이 메서드나 프로퍼티에 접근하려 하면 추가 기능을 제공해주는 특수한 객체이다.

   ► 래퍼 객체는 프로퍼티를 참조할 때 생성되고 참조가 끝나면 사라진다.

 

 

✅ 래퍼 객체(wrapper object)

- 원시 타입에 따라 종류가 다양하다.

   ► String, Number, Boolean, Symbol 라고 부른다.

   ► 래퍼 객체마다 제공하는 메서드도 다르다.

 

- 예시. 인수로 받은 문자열의 모든 글자를 대문자로 바꿔주는 메서드 toUpperCase()

   ► 다음과 같이 동작한다.

   ► 1) 문자열 str은 원시값(문자형)이다.

   ► 2) 원시값의 프로퍼티(toUpperCase)에 접근하느 순간 특별한 객체가 만들어진다.

            /* 이 객체는 문자열의 값을 알고 있으며, toUpperCase()와 같은 유용한 메서드를 가지고 있다. */

   ► 3) 메서드가 실행되고 새로운 문자열이 반환된다.

   ► 4) 특별한 객체는 파괴되고, 원시값 str만 남는다.

let str = "Hello World!";
console.log(str.toUpperCase());

 

- 이 래퍼 객체의 장점은 원시값을 가볍게 유지하면서 메서드를 호출할 수 있다는 점이다.

 

 

📌 String, Number, Boolean은 생성자로의 사용을 지양한다.

- 래퍼 객체를 만드는 방법 중 하나로 아래와 같이 new를 통해 만드는 방법이 있다.

let str = new String("Hello World!");

- 하위 호환성을 위해 이 기능을 남겨두었지만 이런 식으로 만드는건 추천하지 않는다고 한다.

   ► 몇몇 상황에서 혼돈을 불러일으키기 때문

 

- 혼란을 야기하는 이유

   ► 일단 원시값과 new를 이용해 만든 래퍼 객체는 타입부터 다르다.

let str1 = "Hello World!";
let str2 = new String("Hello World!");

console.log(typeof str1); // string
console.log(typeof str2); // object

   ► 또한 객체는 논리 평가 시 무조건 "참(true)"을 반환하기 때문에 원치 않는 결과를 얻을 수도 있다.

let str1; = ""; // 빈 문자열
let str2 = new String(); // 빈 문자열

if (str1) {
	console.log(`str1의 값 : ${str1} , str1 논리평가 결과 : true`);
}
else {
	console.log(`str1의 값 : ${str1} , str1 논리평가 결과 : false`);
}
/* 결과 : str1의 값 : undefined , str1 논리평가 결과 : false */

if (str2) {
	console.log(`str2의 값 : ${str2} , str2 논리평가 결과 : true`);
}
else {
	console.log(`str2의 값 : ${str2} , str2 논리평가 결과 : false`);
}
/* 결과 : str2의 값 :  , str2 논리평가 결과 : true */

 

- 그렇다면 래퍼 객체를 이용하고 싶다면 원시값 형태로만 선언을 해야하는 걸까.

   ► 아니다. new를 붙이지 않고 사용하는 방법도 있다.

   ► 예시

"use strict";

let str1 = "";
let str2 = String(); // new 제거

console.log(typeof str1); // string
console.log(typeof str2); // string

if (str1) {
	console.log(`str1의 값 : ${str1} , str1 논리평가 결과 : true`);
}
else {
	console.log(`str1의 값 : ${str1} , str1 논리평가 결과 : false`);
}
/* 결과 : str1의 값 :  , str1 논리평가 결과 : false */

if (str2) {
	console.log(`str2의 값 : ${str2} , str2 논리평가 결과 : true`);
}
else {
	console.log(`str2의 값 : ${str2} , str2 논리평가 결과 : false`);
}
/* 결과 : str2의 값 :  , str2 논리평가 결과 : false */

- new를 사용하지 않고 String / Number / Boolean을 사용하면 상식에 맞게 인수를 원하는 형의 원시값으로 바꿔준다.

 

📌 null과 undefined는 메서드가 없다.

- 이 두 개의 원시값은 특수 자료형이며, 래퍼 객체도 없고 메서드도 제공하지 않는다.

- 즉, 위의 법칙을 따르지 않는다.

 

 

📌 래퍼 객체에 프로퍼티를 추가할 때 발생하는 일 

- 만약 래퍼 객체에 프로퍼티 ("test": 5)를 추가하면 어떻게 될까

"use strict";

let str = "Hello World!";
str.test = 5;

console.log(str.test);

   ► 엄격 모드(use strinct)인 경우 에러가 발생하고

        /* TypeError: Cannot create property 'test' on string 'Hello World!' */

   ► 비 엄격 모드인 경우 undefined가 출력된다.

 

- 그 이유는 아래와 같이 동작하기 때문이다.

   ► str의 프로퍼티에 접근하려 하면 "래퍼 객체"가 생성된다.

   ► 엄격모드의 경우 : 래퍼 객체를 수정하려고 하면 에러가 발생한다. (래퍼 객체를 수정할 수 없다)

   ► 비엄격모드의 경우 : 래퍼 객체에 프로퍼티 test가 추가된다.

                                      다만, 래퍼 객체는 참조가 끝나면 즉시 삭제된다.

                                      따라서 console.log를 이용해서 프로퍼티 test에 접근하려고 해도 test를 찾을 수 없어 undefined가 출력된다.

 

- 확실히 알아두어야 할 점은 원시값은 객체와 다르다는 점이다.

   ► 기본적으로 원시값은 추가 데이터를 저장할 수 없고

   ► 래퍼 객체는 프로퍼티를 참조할 때 생성되고 참조가 끝나면 그 즉시 삭제된다.

Comments