Language/Javascript

undefined 제대로 알기 (1) undefined? empty? 🧐

joooing 2021. 1. 10. 00:17
반응형

undefined? null? empty? 모두 '없다'는 뜻인 것 같기는 한데.. 뭐가 다른 건지, 어떤 상황에서 뭘 써야하는지 누군가 물어보면 명쾌하게 대답해주지는 못할 것 같았다. 배웠던 개념들을 복습하던 중에 이런 생각이 들어서 그냥 한 번 제대로 알고 넘어가자! 하고 자료들을 찾아봤다. 찾아보고 정리한 결과, 이 중 undefined가 가장 중요한 개념이라는 생각이 들어서 undefined를 위주로 empty나 null과 어떤 점에서 다른지 이야기해보려고 한다. 이 글은 기본적인 의미에 대한 설명은 생략하기 때문에 읽기 전에 이 문서를 먼저 한 번 보고오는걸 추천한다.

 

undefined


Javascript에서 undefined 값이 반환되는 경우는 크게 두 가지가 있다.

 

1. 사용자가 '명시적'으로 지정하는 경우
말 그대로 사용자가 '여기에는 값을 넣지 않을거야'하고 undefined를 통해 알리는 경우이다.

2. Javascript 엔진이 반환하는 경우
Javascript 엔진은 사용자가 어떤 값을 지정할 거라고 예상했는데 하지 않은 경우에 undefined를 반환한다. 어떤 경우에 이런 일이 생기는 지는 이어서 예제와 함께 알아보자. 👇🏻

 

Javascript 엔진이 undefined를 반환하는 경우 (2번)

Javascript 엔진이 알아서 undefined를 반환하는 경우는 아래처럼 세 가지 정도가 있다. 대부분 뭔가 존재할 법도 한데 존재하지 않는 경우인 걸 볼 수 있다. 

 

2-1. 값이 할당되지 않은 변수에 접근할 때

let name;
console.log(name);        // undefined

 

2-2. 존재하지 않는 속성(property)에 접근할 때

let obj = { name : 'jooing' } 
console.log(obj.age);        // undefined

 

2-3. 함수에 return문이 없을 때, 호출되지 않는 함수를 실행할 때

let func = function(){ }; 
let a = func();        // undefined

 

empty

이번 글에서는 Javascript 엔진이 undefined를 반환하는 경우 중 2-1. 값이 할당되지 않은 변수에 접근할 때에 대해 자세히 살펴봄으로써 empty가 무엇인지 설명하려고 한다. 일단 위의 예시를 배열에도 한번 적용해보자.

 

arr1이라는 빈 배열을 만들고 크기만 5로 지정해주었다. 이 상태로 arr1의 모습을 출력했더니 [empty x 5]라고 나온걸 볼 수 있다. empty는 아무 값도 없다는 뜻이다. undefined조차 할당되지 않은, 정말 말 그대로 '비어 있는' 요소를 말한다.

 

let arr1 = [];
arr1.length = 5;
console.log(arr1);    // [empty x 5]

 

 

 

방금 전과 마찬가지로 empty는 이렇게 배열 인스턴스를 생성하기만 했을 때도 나온다.

 

let arr2 = new Array(5);
console.log(arr2);    // [empty x 5]

 

 

 

반면, 이렇게 undefined를 직접 배열에 넣어줘 보면 empty와는 다르게 동작하는 것을 확인할 수 있다. undefined 3개가 들어있는 배열을 할당하면, 그대로 undefined들이 할당된 채로 출력된다.

 

let arr3 = [undefined, undefined, undefined];
console.log(arr3);     // [undefined, undefined, undefined]

 

 

 

 

위의 예시들을 통해 empty값은 물론, undefined조차 할당되지 않은 '비어 있는' 상태라는 것을 확인했다. 잘 생각해보면 배열도 객체 중 하나이다. 그리고 객체의 경우 값이 존재하지 않는 속성 = 존재하지 않는 속성이라고 할 수 있는데, 이렇게 존재하지 않는 속성에는 당연히 접근도 할 수 없다.

 

🗣 속성 : " 값이 없으면 나도 없는거나 마찬가지야! "

배열의 속성은 바로 index라고 할 수 있는데, 여기에 방금 두 가지 사실을 조합해서 생각해보면 배열의 경우에도 값이 존재하지 않는 index = 존재하지 않는 index라고 할 수 있고, 이런 존재하지 않는 index에는 접근할 수 없다는 결론이 나온다.

 

지금까지 이야기를 종합해보자.

 

empty ⇒ 비어 있는 상태 ⇒ 값이 존재하지 않음 ⇒ 속성에 접근 불가!

 

undefined vs empty

지금까지의 이야기가 중요한 이유는, 속성에 접근이 불가능하면 순회 대상에서 제외되기 때문이다. 대표적인 순회와 관련된 배열 메서드에는 forEach, map, filter, reduce.. 등이 있었다. (메서드 사용법) 이런 배열 메서드들에 undefined와 empty를 적용해보면 둘의 차이점이 드러난다.

 

그럼 먼저 undefined를 할당한 배열에 순회 메서드들이 적용되었을 때부터 살펴보자. 비록 연산을 하면 NaN이 나오기도 하지만, 모든 경우에 인덱스에 접근할 수 있는 것을 볼 수 있다. 다시말해 할당된 undefined는 순회 대상에 포함되는 것이다.

let arr1 = [undefined, 10];

arr1.forEach(function (val, i) {console.log(val, i);};
// undefined 0
// 10 1

arr1.filter(function (val) {return !val;});
// [undefined]

arr1.map(function (val, i) {return val + i;});
// [NaN, 11]

arr1.reduce(function (acc, cur) {return acc + cur;}, '');
// undefined10

 

 

이제 empty에 순회 메서드를 적용해보며 undefined와는 어떻게 다른지 살펴보자. 아래의 예제들을 쭉 보면 empty부분은 연산에 포함되지 않을 뿐 아니라, 인덱스 자체에 접근하지 못하는 것을 볼 수 있다. empty는 순회대상에서 제외되기 때문에 메서드도 무시하고 지나가버리게 되는 것이다.

 

let arr2 = [];
arr2[1] = 10;
console.log(arr2);    
// [empty, 10]

arr2.forEach(function (val, i) {console.log(val, i);};
// 1 10  (0번째 인덱스 제외)

arr2.filter(function (val) {return !val;});
// []

arr2.map(function (val, i) {return val + i;});
// [empty, 2]

arr2.reduce(function (acc, cur) {return acc + cur;}, '');
// 10

 

 

요약


✔️ Javascript에서 undefined 값이 반환되는 두 가지 경우

1. 사용자가 '명시적'으로 지정하는 경우
2. Javascript 엔진이 반환하는 경우
     2-1. 값이 할당되지 않은 변수에 접근할 때
     2-2. 존재하지 않는 속성(property)에 접근할 때
     2-3. 함수에 return문이 없을 때, 호출되지 않는 함수를 실행할 때

✔️ empty

empty = 비어 있는 상태 ⇒ 값이 존재하지 않음 ⇒ 속성에 접근 불가 ⇒ 순회 대상에서 제외

 

지금까지 여러 예시들을 통해 '비어있는(empty)' 경우와 'undefined를 할당'한 경우는 순회를 할 때 다르게 취급받는다는 것을 확인했다. 다음 편에서는 Javascript에서 undefined값이 반환되는 두 가지 경우와 연관해 'null'이 왜 등장했고, 어떤 상황에 사용해야 하는 지 소개할 예정이다. 👏

 

 

 

 

반응형