티스토리 뷰

Javascript

#4 암묵적 타입 변환

심재철 2019. 7. 29. 10:40

https://www.notion.so/simsimjae/4-25266bff47204219bf2863fed86c1756

+연산자에 대해서는 피연산자를 모두 문자열로 변환시켜준다. 1 + "2" // "12" 1 + "js" // "1js"

해석 순서는 왼쪽에서 오른쪽이다.

1 + 2 + "1" // "31" (1 + 2) + "1" // "31" 1 + "2" + 1 // "121" (1 + "2") + 1 // "121"

-, *, / 연산자에 대해서는 피연산자를 모두 숫자로 만든다.

1 - '1' // 0 1 * '10' // 10 1 / 'one' // NaN, 'one'을 숫자로 변환할수없음.

>에 대해서는 피연산자를 모두 숫자로 만든다음 표현식이 실행된다.

'1' > 0 // true, '1'이 1로 변환됨.

+를 하나만 쓴경우 피연산자를 숫자로 바꿔버린다.

// 문자열 타입 +'' // 0 +'0' // 0 +'1' // 1 +'string' // NaN // 불리언 타입 +true // 1 +false // 0 // null 타입 +null // 0 // undefined 타입 +undefined // NaN // 심볼 타입 +Symbol() // TypeError: Cannot convert a Symbol value to a number // 객체 타입 +{} // NaN +[] // 0 +[10, 20] // NaN +(function(){}) // NaN

if문 안에서도 암시적 형변환이 일어난다. falsy, truthy값을 기준으로 변환된다.

if ('') console.log('1'); if (0) console.log('3'); if ('str') console.log('4'); if (null) console.log('5');

이렇듯 자바스크립트 엔진은 상황(컨텍스트)에 맞게 코드가 실행되도록 암묵적 타입 변환을 시켜준다.


객체를 toString() 하는 경우 - 숫자문자인경우

const foo = { toString: () => 4 } 2 * foo // 8 2 / foo // 0.5 2 + foo // 6 "four" + foo // "four4"

여기서 foo가 문자열 "4"를 리턴하기 때문에 2 * "4" 는 NaN이 아닐까? 라고 생각할 수 있다.

하지만, 위와 같이 toString에서 숫자문자를 리턴하게 되면 숫자로 암묵적 변환된다.

아래와 같이 동작한다.

2 * foo 2 * foo.toString() 2 * Number("4"); 2 * 4 = 8


객체를 toString() 하는 경우 - 숫자문자가 아닌 경우

const baz = { toString: () => "four" } 2 * baz // NaN 2 + baz // 2four const bar = { toString: () => "2" } 2 + bar // "22" 2 * bar // 4

이번에는 baz가 문자열 "four"를 리턴하게 해봤다.

그랬더니 NaN이 출력된것을 볼 수 있다. 객체를 문자열로 변환했기 때문에 당연한 결과이다.

다만 위 예제에서는 숫자문자2를 리턴했기 때문에 암묵적 변환이 일어난것이다.

valueOf메소드

const foo = { valueOf: () => 3 } 3 + foo // 6 3 * foo // 9

  1. 문자열 + 객체

    3 + foo 3 + foo.valueOf() 3 + 3 //6
  2. 숫자 + 객체

    "3" + foo "3" + foo.valueOf() "3" + 3 // "33"

위와 같은 두가지 상황에서 자바스크립트 엔진은 객체의 valueOf메소드를 호출해서 객체를 값으로 만들어준다.

객체에 toString과 valueOf가 둘다 정의되어 있으면 valueOf가 우선순위를 갖는다.

falsy와 truthy

  1. false
  2. 0
  3. null
  4. undefined
  5. ""
  6. NaN
  7. -0

위 7가지는 모두 false로 취급되고 그 외에 나머지는 모두 true로 취급된다.

자바스크립트의 암시적 형 변환을 완벽히 이해했다고 하더라도, 다른사람과의 협업을 위해서 명시적 형변환을 써주는게 좋다.

const add = (number) => { if(!number) new Error("Only accepts arguments of type: number") }

위 함수는 숫자를 처리하기 위한 함수이다. 숫자가 아닌게 들어오면 에러를 리턴한다.

이 함수는 자바스크립트의 암시적 형 변환에만 의존하고 있다.

여기서 만약 add(0)을 호출한다면 숫자인 0을 전달했음에도 불구하고 에러가 난다.

왜냐면? 자바스크립트에서 숫자 0은 false로 취급되기 때문에 if문이 실행됬기 때문이다.

이런 현상을 막으려면 if 문에서 typeof로 한번더 체크해주는게 좋다.

const add = (number) => { if (typeof number !== "number") new Error("Only accepts arguments of type: number") // your code }

NaN은 자기 자신과도 같지 않다. 그 누구와도 같지 않다. NaN === NaN // false

ES6의 Number.isNaN() 메소드

  • 자바스크립트에서 NaN은 ==나 ===로 비교가 불가능하기 때문에(무조건 false기 때문에) 이 메소드로 NaN인지 확인해야 한다.

  • 인자로 넘어온것이 NaN인지 판단해주는 메소드

  • 판단하기 전에 인자를 Number()함수로 암시적 형변환을 시켜준 뒤에 동작한다.

    const isNaN = (val) => { const num = Number(val); //숫자로 변환 return coerce !== num ? true : false }

    isNaN("1a") // true, 문자열 "1a"는 NaN이다 isNaN("1") // false, 문자열 "1"은 NaN이 아니다. 즉, 숫자다. isNaN("as") // true isNaN(NaN) // true isNaN(10) // false

단축평가

'Cat' && 'Dog' // 'Dog' 'Cat' || 'Dog' // 'Cat'

  • 'Cat'과 'Dog'모두 truthy값이다. 그런데 &&(논리곱)연산자가 true를 리턴하게 된것은 두번쨰 피연산자인 'Dog'가 true임을 알고 나서이다. 따라서 true가 아닌'Dog'를 리턴하게 된다.
  • 두번째에서 마찬가지로 ||(논리합)연산자는 피연산자 둘중 하나만 true 여도 전체가 true이다. 첫번째 피연산자가 이미 true이기 때문에 ||가 true다를 결정한것은 첫번째 피연산자이며, 따라서 'Cat'을 리턴하게 된다.
  • 한마디로, 연산자의 최종판단을 도와준 피연산자를 리턴하는것이 단축평가이다.

단축평가 - 객체의 프로퍼티가 Null인지 판단할때 사용

var elem = null; console.log(elem.value); // TypeError: Cannot read property 'value' of null

  • 그냥 elem.value를 하게 되면 elem이 null일때 에러가 난다.

    var elem = null; console.log(elem && elem.value); // null

  • 이렇게 코드를 단축평가로 바꿔주게 되면 elem이 null이더라도 에러가 나지 않는다.

  • 논리곱(&&)연산자의 결과를 결정하게 만든 피연산자는 elem(null)이므로 콘솔에null이 찍힘.

  • elem && elem.value를 하게 되면 피연산자 elem과 elem.value가 모두 true일때 elem.value를 리턴하게 되므로 좀 더 안정적인 코드가 되었다.

     

단축 평가의 활용 - 함수의 매개변수 초기화

// 단축 평가를 사용한 매개변수의 기본값 설정 function getStringLength(str) { str = str || ''; return str.length; } getStringLength(); // 0 getStringLength('hi'); // 2 // ES6의 매개변수의 기본값 설정 function getStringLength(str = '') { return str.length; } getStringLength(); // 0 getStringLength('hi'); // 2

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함