JS

#33가지 Javascript 필수 개념 - 4. Type Coercion

728x90

본 내용은 아래의 링크를 참조하여 작성되었습니다

(https://github.com/leonardomso/33-js-concepts#4-implicit-explicit-nominal-structuring-and-duck-typing)

 

 

* Type Coercion

 

형 변환 (Type Coercion) 은 A 라는 예상 타입으로 변수의 타입이 결정되기를 바랬으나, 실제로는 B 라는 예상치 못한 타입이 나와서 이를 다시 A 타입의 변수로 바꾸는 작업을 말한다

 

예를 들면, Number 타입의 변수가 오기를 바랬으나, 실제로는 String 형태의 타입이 와서 값을 Number 타입으로 다시 변환하는 작업 같은 것을 말한다.

 

형 변환에는 두가지가 존재하는데, 

Implicit Type Coercion (암묵적 형 변환), Explicit Type Coercion (명시적 형 변환) 이 있다.

 

 

 

* Implicit Type Coercion

이 타입의 형 변환은 프로그래머가 직접적으로 코드를 작성해서 변수의 type 을 바꾸는게 아니라

JS Engine 에 의해서 예상되는 타입 값으로 자동으로 바꾸는 작업이다.

 

이에 대한 여러가지 사례들을 살펴보자.

 

 -1. String

먼저 문자열을 암시적 형 변환을 할때인데, 문자열을 피연산자(operand) 로 하는 -, *, %, / 와 같은 수치 연산을 할 경우 JS 의 내장함수인 Number(string) 을 통해서 변환하는 것과 동일한 결과를 가져온다.

 

string type 변환

위 그림을 보면, 

3 * "3" 이나 3 * Number("3") 이나 똑같은 결과를 가져오는 것을 볼 수 있다.

다른 연산도 마찬가지의 결과를 보여준다.

3 * "3" 같이 계산되는 것을 Implicit Type Coercion 이라 하고,

3 * Number("3") 같이 계산되는 것은 프로그래머가 직접 "3" 에 대해서 Number 타입으로 변환하라 지시 했기 때문에 Explicit Type Coercion 이 된다.

 

 

다만 이런 연산은 문자열에 들어간 문자들이 숫자 문자 일때만 가능하다

예를 들면 아래와 같이 문자열을 선언한 경우 NaN 으로 리턴된다.

 

string type 변환 오류

 

위에서 언급하지 않은 숫자 연산이 하나 있는데 그것은 바로 + 연산이다.

+ 연산의 경우, JS 에서는 두가지로 연산이 되는데 아래와 같다

 

 -1) Mathematical Addition (숫자 더하기)

 -2) String Concatenation (문자열 합치기) 

 

문자열의 경우 1) 의 경우가 아니라, 2) 의 경우로 처리된다.

위 그림을 보면, 3 + "3" , 2 + "2" 의 결과가 '33' , '22' 로 바뀌었지만,

밑의 두가지 경우는 숫자 끼리의 연산이라서 1) 의 경우로 처리가 되었다.

 

string 을 활용해서 + 연산을 할 경우 숫자가 문자열로 바뀌어서 처리되기 때문에

3 + "3" 에서 앞의 3 이 문자 "3" 으로 바뀌어서 문자열 합치기가 된것이다.

 

 

 -2. Object

객체의 경우 형 변환이 이뤄질때, 아래 그림 처럼 [object Object] 로 변환되어 나타난다.

object type conversion

모든 JS Object 들은 toString method 와 valueOf method 를 상속받는데, 

이 둘을 이용하면 Object 타입에 대한 형 변환 값을 바꿀 수가 있다.

 

 -1) toString()

 -2) valueOf()

 

-1) toString()

toString 은 Object 타입의 변수를 문자열 타입으로 변환하려고 할 때마다 사용되는 method 로, 아래와 같은 예제들로 사용가능하다.

object type conversion

또한 toString() 을 활용해서 숫자 연산도 가능하다

object type conversion

 

이런 연산이 왜 가능한 걸까?

 

그 이유는 method overriding 을 사용하기 때문이다.

JS 의 모든 Object 의 최상단 부모 객체는 Object 이다.

Object 자체적으로 수많은 method 를 가지고 있는데

위에서 선언한 obj 라는 변수가 Object 타입으로 선언됨과 동시에 

toString() 를 메소드 오버라이딩 형태로 사용하고 있기 때문이다.

 

그래서 toString 을 어떻게 선언하는가에 따라서 형변환 값이 달라지게 된다.

 

 

(자세한 Object 의 method 종류는 아래 사이트를 참고 바람)

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object

 

Object

The Object class represents one of JavaScript's data types. It is used to store various keyed collections and more complex entities. Objects can be created using the Object() constructor or the object initializer / literal syntax.

developer.mozilla.org

 

 

-2) valueOf()

또 다른 예시로 valueOf() 를 살펴보면,

valueOf() 는 Object 를 numeric value 로 표현하기 위해서 쓰이는데 그 예시는 아래와 같다

 

object type conversion

만약 valueOf 와 toString 두개를 메소드 오버라이딩 하면 어떻게 될까?

 

아래의 예시는 valueOf 와 toString 둘다 결과값으로 숫자가 되게 만든 예시이다.

 

object type conversion

연산을 함에 있어서 valueOf 가 더 우선적으로 처리되는 것을 알 수 있다.

 

그런데 여기서 한가지 의문인것은,

분명 앞에서는 valueOf 가 숫자값으로 쓰이고, toString 은 문자열 변환을 할 때 쓰인다고 했는데

왜 "test" + obj 할 때 'test9' 가 아니라 'test3' 가 되었을까?

 

 

그 이유는 아래와 같이 요약된다,

 

 

1. valueOf() 의 결과 값은 단순히 numeric value 가 리턴되는 것이 아니라, 객체의 primitive value 를 리턴하기 때문이다.

2. + 연산자는 앞서 언급한 '숫자 덧셈', '문자열 합치기' 중에서 어떤 연산을 할지 선택할때, 피연산자(operand) 에 해당하는 값에 대한 primitive value 를 먼저 수집하고 난뒤에 결정하기 때문이다.

 

 

valueOf 에 대한 mdn 설명 문서를 보면

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf

 

Object.prototype.valueOf()

The valueOf() method returns the primitive value of the specified object.

developer.mozilla.org

 

"The valueOf() method returns the primitive value of the specified object." 

라고 써있는 것을 볼 수 있다.

그래서 obj 변수의 primitive value 는 결국 valueOf: () => 3 에 의해서 3으로 결정이 된 것이며,

 

+ 연산자가 연산을 수행하기에 앞서서 obj 의 primitive value, type 이 숫자형인 3 인것을 알았으니

문자열 합치기를 수행한 것이고 이에 따른 결과가

'test3' 가 된 것이다. 

 

이에 대한 좀 더 자세한 설명을 보려면 아래의 사이트를 참조하기 바란다

https://stackoverflow.com/questions/2485632/valueof-vs-tostring-in-javascript

 

valueOf() vs. toString() in Javascript

In Javascript every object has a valueOf() and toString() method. I would have thought that the toString() method got invoked whenever a string conversion is called for, but apparently it is trump...

stackoverflow.com

 

 -3 Boolean

Boolean 타입이 아닌 다른 값들도 Boolean 타입의 값으로 바뀔 수가 있다.

 

대부분의 언어가 공통적으로 0 값은 false, 0 이외의 값은 true 로 처리되는데,

 

JS 의 경우 다음과 같은 7가지의 값이 false 로 처리된다.

 

-1) false

-2) -0

-3) null

-4) undefiend

-5) NaN

-6) ""

-7) 0

 

false type

Boolean 타입의 형 변환을 할 때 주의 할 점은

조건문을 작성해서 처리할 때 이다.

 

예를들면, 아래와 같은 경우를 보면

Boolean Error

위의 printNum 함수를 보면 함수 이름에서도 알 수 있듯, 숫자를 출력하는 것을 의도하고 만든 함수이다.

그래서 num 매개변수를 받아서 숫자가 아니면 에러를 내보내고자 했으나,

0 은 숫자임에도 불구하고 오류를 나타낸다

 

왜냐면 if 문에서 0 은 false 로 처리되어 !0 이므로 true 가 되서 오류를 보냈기 때문이다.

즉, 0 이 Boolean 타입으로 형 변환 처리 되었기 때문이다.

 

이런 경우에는 다음과 같이 써서 오류를 해결한다

Boolean error2

 

 

 

지금까지 JS 의 형 변환에 대해서 알아보았다.

 

개인적으로 JS 의 큰 단점 중 하나가 바로 타입에 대한 모호함, 애매함 이라 생각한다

웹 사이트를 만들다 보면, JS 가 타입 처리에 있어서 애매할 때가 종종 있었다.

사이트를 통해 받아온 값을 사이트 작성을 위한 코드 개발시에 숫자형 자료형이 오기를 기대하고 코드를 짰으나,

문자열로 날라온다던가 하는 그런 문제들

 

하지만 이 문제는 typescript 의 등장으로 문제 해결이 되었다.

 

 

 

728x90