본문 바로가기
책을 읽어봅시다/무던한 개발자를 위한 모던한 자바스크립트

[무던한 개발자를 위한 모던한 자바스크립트]제어구조

by upswp 2022. 2. 16.
안녕하세요 Samuel 입니다 : )

해당 책의 내용중 저에게 필요한 일부를 메모하는 방식으로 작성하였으며( +@ 느낀점도 살짝살짝 적어봤어요! ), 추가적으로 구글링과 공식문서를 참고해서 글을 작성해봤습니다.

한빛미디어 <나는 리뷰어다> 활동을 위해서 책을 제공받아 작성된 서평입니다.


제어구조

불리언화

자바스크립트의 조건( if 문의 조건 등 )은 불리언 값을 사용한다. 0, NaN, null, undefined, 빈문자열은 조건을 거짓으로 만드는 ‘일종의 거짓(falsish)’값이다. 이를 제외한 모든 다른 값은 ‘일종의 참(truish)’값이 되며 조건을 참으로 만든다. 이렇게 참이나 거짓으로 분류되는 값을 ‘거짓으로 평가되는 값'이나 ‘참으로 평가되는 값'이라고 부른다. 다만 이들이 공식 언어 명세에 사용되는 용어는 아니라는 점을 기억하다.

처음에는 불리언 변환 규칙이 합리적인 것 처럼 보일 수 있다. 다음 코드처럼 performance라는 변수를 만들었는데 이 변수가 undefined가 아닌 상황에서만 이 변수를 사용하려 한다고 가정하자.

if(performance) ... //위험함

performance가 undefined이면 예상대로 테스트가 실패한다. 하지만 performance가 null일때도 테스트가 실패한다는 점이 문제다.

performance가 빈 문자열이라면 어떨까? 혹은 숫자 0을 갖는다면? 역시나 여러가지 고려해야하는 상황에 놓이게 된다.

이 부분에서 조금 더 명확하게 코드를 작성할 필요가 있다.

if(performance !== undefined) ...

혼합비교

한 피연산자가 숫자이고 다른 피연산자는 숫자로 변환된 상황을 가정하자. 다른 피연산자는 원래 문자열이었다. 이 문자열이 숫자를 포함한다면 변호나 과정에서 문자열은 숫자로, 문자열이 비어있었다면 0으로, 이외의 경우에는 NaN으로 변환된다. 특히 NaN을 비교하면 결과는 항상 false다(심지어 NaN ≤ NaN도 false가 된다.)

'42' < 5 // '42'는 숫자 42로 변환되므로 false
'' < 5 // ''는 숫자 0으로 변환되므로 false
'Hello' <= 5 // 'Hello'는 NaN으로 변환되므로 false
5 <= 'Hello' // 'Hello'는 NaN으로 변환되므로 false

이번에는 한쪽 피연산자가 배열인 경우를 살펴보자.

[4] < 5 // [4]는 숫자 4로 변환되므로 true
[] < 5 // []는 숫자 0으로 변환되므로 true
[3,4] < 5 // [3,4]는 NaN으로 변환되므로 false

이제 느슨한 비교 연산자 x == y가 어떻게 동작하는지 더 자세히 살펴보자.

  • 두 피연산자의 형식이 같다면 이들을 직접 엄격히 비교한다.
  • undefined와 null은 자신과 서로의 값에는 대략 같음으로 취급된다. (다른값에는 적용되지 않음)
  • 한 피연산자가 숫자고 다른 피연사자가 문자열이면 문자열을 숫자로 변환한 다음 엄격한 비교를 수행한다.
  • 한 피연산자가 불리언 값이면 두 피연산자를 모두 숫자로 변환한 다음 엄격한 비교를 수행한다.
  • 한 피연산자가 객체면 객체를 기본형으로 변환한 다음 느슨한 비교를 수행한다.
'' == 0 // ''는 0으로 변환되므로 true
'0' == 0 // '0'는 0으로 변환되므로 true
'0' == false // 둘다 0 으로 변환되므로 true
undefined == false // undefined은 자신이나 null 형식하고만 같으므로 false

하 .. 느슨한 연산자와 == 와 ≠ 를 피하는 방식으로 엄격한 비교를 하는것이 좋을 것 같다. 실제로 이런 모든 것을 생각하고 개발하기에는 위험부담이 매우 크기 때문이다.

논리연산자

개발을 진행하면서 개인적으로 가장 많이 놓치는 부분이라고 생각이 드는 부분이다. 어쩌면 가장 쉬우면서 가장 간과하면서 개발을 진행하는것이 바로 논리연산자라고 생각한다. ( 특히 && .. )

&&와 || 연산자는 평가를 게을리 하는 경향이 있다. 즉 왼쪽의 피연산자만으로 결과가 결정되면 ( && 에서는 거짓으로 평가되는 값, || 에서는 참으로 평가되는 값 ) 오른쪽 피연산자는 평가하지 않는다.

if( i < a.length && a[i] > 0 ) // i >= a.length이면 a[i] > 0를 평가하지 않는다.

&&와 || 연산자를 불리언이 아닌 피연산자를 사용하면 한 피연산자를 표현식의 값으로 내보낸다. 왼쪽 피연산자가 결과를 결정하는 상황이라면, 왼쪽 피연산자가 표현식의 값이 되고 오른쪽 피연산자는 평가하지 않는다. 이런 상황이 아니라면 오른쪽 피연산자가 표현식의 값이 된다.

let result = arg && arg.someMethod()

이 코드는 arg의 메서드를 호출하기 전에 arg가 undefined나 null이 아님을 확인한다. arg가 undefined이거나 null이면 결과도 undefined나 null 이 된다. 이 코드는 arg가 0, 빈문자열, false면 의도한 대로 동작하지 않는다. 메서드가 undefined나 null을 반환할때 기본값을 제공하는 용도로 사용할 수 있다.

let result = arg.someMethod() || defaultValue

이 코드도 메서드가 0, 빈문자열, false를 반환하면 제대로 동작하지 않는다.

어떤 대상이 undefined나 null이 아닐때만 값을 사용할 수 있는 편리한 수단이 필요하다.

x ?? y 표현식의 결과는 x가 undefined나 null 이 아니면 x , 그렇지 않으면 y가 된다.

let result = arg.someMethod() ?? defaultValue

메서드가 undefined나 null을 반환할 때만 기본값을 사용한다. x?.프로퍼티명 은 x가 undefined나 null 이 아니면 프로퍼티를 반환하고 그렇지 않으면 undefined를 반환한다.

let recipient = person?.name
let recipientLentgh = person?.name?.length

참고문서

무던한 개발자를 위한 모던한 자바스크립트