JavaScript: Null vs Undefined
В JavaScript (Typescript) есть два низкоуровневых типа: null и 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 где это возможно.