JavaScript: Null vs Undefined
В JavaScript (Typescript) есть два низкоуровевых типа: null
и undefined
. И они предназначены для обозначения разных вещей:
- Что-то, что не было инициализировано:
undefined
- Что-то, что в настоящий момент недоступно:
null
Проверка
На самом деле придется иметь дело с обоими типами. Интересно то, что в JavaScript, при использовании ==
эти типы равны только друг с другом:
console.log(null == null); // конечно true
console.log(undefined == undefined); // конечно true
console.log(null == undefined); // true (!)
console.log(0 == undefined); // false
console.log('' == undefined); // false
console.log(false == undefined); // false
Рекомендуется проверять оба значения. При использовании == null
.
// typescript
function foo(arg: string | null | undefined) : void {
if (arg != null) {
// arg должен быть строкой, так как
// != исключает `null` и `undefined`
}
}
Можно использовать и!= undefined
, но!= null
короче и понятней.
Проверка на корневом уровне
На верхнем, корневом, глобальном уровне, если мы используем foo
и foo
в данный момент не существует при попытке использовать == null
получим исключение ReferenceError
. Это следует запомнить и использовать для проверки на глобальном уровне typeof
if (typeof someGlobal !== 'undefined') {
// здесь можно использовать someGlobal
console.log(someGlobal)
}
Ограничить явное использование undefined
Вместо подобных
function foo() {
return {a:1, b:2}
return {a:1, b:undefined}
}
использовать аннотацию типов
// typescript
function foo(a: number, b: number) {
// if
return {a:1, b:2}
// else
return {a:1}
}
Не использовать undefined
как средство валидации
Пример "ужасной" функции
// typescrypt
function toInt(str: string) {
return str ? parseInt(str) : undefined
}
гораздо лучше сделать так
// typescrypt
function toInt(str: string): { valid: boolean, int?: number} {
const int = parseInt(str)
if (isNaN(int)) {
return { valid: false }
} else {
return { valid: true, int }
}
}
Стиль Node
Функции обратного вызова ((err, data) => {/* ...*/}
) обычно вызываются с err
установленным в null
. И это не ошибка. Это стандартное правило, которое позволяет просто проверить есть ошибки или нет:
// node.js
fs.readFile('file', 'utf8', (err, data) => {
if (err) {
// has error
} else {
// no error
}
})
Создавая код для Node.js следует придерживаться этого правила и использовать null
.
JSON сериализация
Стандарт JSON поддерживает null
, но не undefined
.
null
или undefined
Если посмотреть на правила команды Typescrypt, то увидим следующее - Use undefined. Do not use null.
Однако в NodeJS код использует null для аргументов ошибок, как правило "Что-то недоступное сейчас". Наверное следует использовать null
и undefined
в зависимости от контекста, отдавая предпочтение undefined
где это возможно.