- Published on
null과 undefined의 차이, 그리고 역사
- Author
- Name
- yceffort
ECMAScript 언어 명세 상의 차이
-
undefined
: 변수에 값이 할당되지 않았을 때 사용된다. https://tc39.es/ecma262/#sec-undefined-value primitive value used when a variable has not been assigned a value -
null
: 의도적으로 어떤 객체의 값이 비어 있다는 것을 나타낼 때 사용된다. primitive value used when a variable has not been assigned a value primitive value that represents the intentional absence of any object value
다른 언어와 다르게, 두개의 non-value가 있는 것은 자바스크립트 설계의 실수라고 한다. 그러나 이것이 지금까지 사용되고 있는 것은 자바스크립트가 구버전과의 호환성을 절대로 깨뜨리지 않는 다는 원칙이 있기 때문이다. 비슷한 사례로 typeof null
이 있다.
자바스크립트가 많은 영감을 받은 자바에서는, 변수의 정적 타입에 따라 값을 초기화 한다.
- 객체 타입의 변수는
null
로 초기화 한다. - 원시 타입의 변수는 각자의 초기 값으로 초기화 한다. 숫자의 경우 0 이다.
자바스크립트의 경우에는, 변수가 객체가 될 수도 있고, 원시값이 될 수도 있다. 그러므로 만약 null
이 "객체가 아니다" 라면, 자바스크립트는 "객체도 아니고 원시값도 아닌" 초기 값이 필요해 진다. 그것이 바로 undefined
다.
undefined가 나오는 경우
// 초기 값을 주지 않은 경우
let var
// 객체에서 정의 하지 않은 속성에 접근하는 경우
const obj = {}
obj.prop
// 함수의 리턴이 없는 경우
function func() {}
assert.equal(func(), undefined)
// 리턴은 있는데 아무것도 안하는 경우
function func() {
return
}
assert.equal(func(), undefined)
function func(x) {
assert.equal(x, undefined)
}
// 정의 되지 않은 파라미터
func()
undefined?.prop
null?.prop
null이 나오는 경우
// 프로토타입의 종점
Object.getPrototypeOf(Object.prototype) // null
// 정규식
/a/.exec('x') // null
// JSON은 undefined를 지원 하지 않는다.
JSON.stringify({a: undefined, b: null}) // "{"b":null}"
undefined와 null을 특별하게 처리하는 연산자
함수 파라미터의 기본값
함수 파라미터의 기본값은 두가지 경우에서만 사용된다.
- 파라미터가 존재하지 않는 경우
- 파라미터의 값이
undefined
인 경우
function func(arg = 'abc') {
return arg
}
console.log(func()) // abc
console.log(func(undefined)) // abc
console.log(func(null)) // null
분해연산자의 기본값과 undefined
위의 기본값 예제와 동일하게 동작한다.
const [a = 'a'] = [] // a
const [b = 'b'] = [undefined] // b
const { prop: c = 'c' } = {} // c
const { prop: d = 'd' } = { prop: undefined } //d
const [e = 'e'] = [null] // null
const { prop: f = 'f' } = { prop: null } // null
옵셔널 체이닝
값이 nullish한 경우 (null
undefined
) undefined
를 리턴한다.
function getProp(obj) {
return obj?.prop
}
getProp({ prop: 123 }) // 123
getProp(undefined) // undefined
getProp(null) // undefined
undefined, null, nullish coalescing (null 병합 연산자)
||
와는 다르게 nullish
한 값에 대해서만 대응한다.
undefined ?? 'default value' // default value
null ?? 'default value' // default value
0 ?? 'default value' // 0
'' ?? 'default value' // ''
null 병합 할당 현산자인 ??=
도 마찬가지로 동작한다.
결론(?)
명시적으로 값이 없다는 걸 나타내고 싶다면, null
을 쓰는게 좋다. undefined
는 기본값 할당, JSON에서 생략되는 등 의도치 않은 동작을 나타낼 수 있다. 내가 의도적으로 빈값을 두고 싶다면, null
이 나은 것 같다. 그렇다고 undefined
가 내가 짠 코드에서 안나오는 것은 아닐 것이다. 말하고 싶은 것은 의도적으로 빈값을 집어 넣을 때 둘중에 null
을 더 선호한다 정도일 것이다. 그러나 이건 어디까지나 내취향의 문제일 뿐, 적절히 헷갈리지만 않게 쓰면 될 것 같다.