본 내용은 아래의 링크를 참조하여 작성되었습니다
* 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) 을 통해서 변환하는 것과 동일한 결과를 가져온다.
위 그림을 보면,
3 * "3" 이나 3 * Number("3") 이나 똑같은 결과를 가져오는 것을 볼 수 있다.
다른 연산도 마찬가지의 결과를 보여준다.
3 * "3" 같이 계산되는 것을 Implicit Type Coercion 이라 하고,
3 * Number("3") 같이 계산되는 것은 프로그래머가 직접 "3" 에 대해서 Number 타입으로 변환하라 지시 했기 때문에 Explicit Type Coercion 이 된다.
다만 이런 연산은 문자열에 들어간 문자들이 숫자 문자 일때만 가능하다
예를 들면 아래와 같이 문자열을 선언한 경우 NaN 으로 리턴된다.
위에서 언급하지 않은 숫자 연산이 하나 있는데 그것은 바로 + 연산이다.
+ 연산의 경우, 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] 로 변환되어 나타난다.
모든 JS Object 들은 toString method 와 valueOf method 를 상속받는데,
이 둘을 이용하면 Object 타입에 대한 형 변환 값을 바꿀 수가 있다.
-1) toString()
-2) valueOf()
-1) toString()
toString 은 Object 타입의 변수를 문자열 타입으로 변환하려고 할 때마다 사용되는 method 로, 아래와 같은 예제들로 사용가능하다.
또한 toString() 을 활용해서 숫자 연산도 가능하다
이런 연산이 왜 가능한 걸까?
그 이유는 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
-2) valueOf()
또 다른 예시로 valueOf() 를 살펴보면,
valueOf() 는 Object 를 numeric value 로 표현하기 위해서 쓰이는데 그 예시는 아래와 같다
만약 valueOf 와 toString 두개를 메소드 오버라이딩 하면 어떻게 될까?
아래의 예시는 valueOf 와 toString 둘다 결과값으로 숫자가 되게 만든 예시이다.
연산을 함에 있어서 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
"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
-3 Boolean
Boolean 타입이 아닌 다른 값들도 Boolean 타입의 값으로 바뀔 수가 있다.
대부분의 언어가 공통적으로 0 값은 false, 0 이외의 값은 true 로 처리되는데,
JS 의 경우 다음과 같은 7가지의 값이 false 로 처리된다.
-1) false
-2) -0
-3) null
-4) undefiend
-5) NaN
-6) ""
-7) 0
Boolean 타입의 형 변환을 할 때 주의 할 점은
조건문을 작성해서 처리할 때 이다.
예를들면, 아래와 같은 경우를 보면
위의 printNum 함수를 보면 함수 이름에서도 알 수 있듯, 숫자를 출력하는 것을 의도하고 만든 함수이다.
그래서 num 매개변수를 받아서 숫자가 아니면 에러를 내보내고자 했으나,
0 은 숫자임에도 불구하고 오류를 나타낸다
왜냐면 if 문에서 0 은 false 로 처리되어 !0 이므로 true 가 되서 오류를 보냈기 때문이다.
즉, 0 이 Boolean 타입으로 형 변환 처리 되었기 때문이다.
이런 경우에는 다음과 같이 써서 오류를 해결한다
지금까지 JS 의 형 변환에 대해서 알아보았다.
개인적으로 JS 의 큰 단점 중 하나가 바로 타입에 대한 모호함, 애매함 이라 생각한다
웹 사이트를 만들다 보면, JS 가 타입 처리에 있어서 애매할 때가 종종 있었다.
사이트를 통해 받아온 값을 사이트 작성을 위한 코드 개발시에 숫자형 자료형이 오기를 기대하고 코드를 짰으나,
문자열로 날라온다던가 하는 그런 문제들
하지만 이 문제는 typescript 의 등장으로 문제 해결이 되었다.
'JS' 카테고리의 다른 글
CORS (Cross Origin Resource Sharing) (0) | 2020.08.19 |
---|---|
Axios 와 Fetch (0) | 2020.08.06 |
#33가지 Javascript 필수 개념 - 3. Value Types, Reference Types (0) | 2020.07.29 |
#33가지 Javascript 필수 개념 - 2. Primitive Types (0) | 2020.07.22 |
#33가지 Javascript 필수 개념 - 1. Call Stack. (0) | 2020.07.21 |