Skip to content

Latest commit

 

History

History
122 lines (95 loc) · 7.32 KB

null-undefined.md

File metadata and controls

122 lines (95 loc) · 7.32 KB

Null и Undefined

Бесплатное видео по теме на YouTube

В JavaScript (и, соответственно, TypeScript) есть два нижних типа: null и undefined. Они предназначены для обозначение разных вещей:

  • Что-то еще не инициализированное: undefined.
  • Что-то недоступное в данный момент: null.

Проверяем оба

Факт в том, что вам придется столкнуться с обоими. Просто проверьте их через ==

/// Представьте, что вы делаете `foo.bar == undefined`, где bar может быть одним из:
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 проверить undefined или null. Как правило, нет необходимости делать между ними различия.

function foo(arg: string | null | undefined) {
  if (arg != null) {
    // arg должен быть строкой, поскольку `!=` исключает и null и undefined.
  }
}

Одно исключение: значения undefined корневого уровня, которые мы обсудим далее.

Проверяем undefined корневого уровня

Помните как я сказал вам использовать == null? Конечно помните (ведь это было только что ^). Не используйте его для вещей корневого уровня. В строгом режиме, если вы используете foo и foo является undefined, вы получите исключение ReferenceError и весь стек вызовов прервётся.

Вы должны использовать строгий режим ... и на самом деле компилятор TS включит его для вас, если вы используете модули ... подробнее об этом будет сказано позже, так что не парьтесь :)

Поэтому чтобы проверить задана ли переменная на глобальном уровне, используйте typeof:

if (typeof someglobal !== 'undefined') {
  // someglobal теперь можно безопасно использовать
  console.log(someglobal);
}

Ограничьте явное использование undefined

Потому что TypeScript дает вам возможность документировать ваши структуры отдельно от значений. Вместо того чтобы делать так:

function foo(){
  // if Something
  return {a:1,b:2};
  // else
  return {a:1,b:undefined};
}

вы должны использовать аннотацию типов:

function foo():{a:number,b?:number}{
  // if Something
  return {a:1,b:2};
  // else
  return {a:1};
}

Колбэки в стиле Node

Функции колбеков в стиле Node (вроде (err,somethingElse)=>{ /* что-нибудь */ }) обычно вызываются с err равным null, если нет ошибок. Как бы то ни было, в общем случае просто используйте проверку на истинность:

fs.readFile('someFile', 'utf8', (err,data) => {
  if (err) {
    // сделать что-нибудь
  } else {
    // ошибок нет
  }
});

Когда создаёте свои собственные API, в подобных ситуациях нормально использовать null для согласованности. Но, честно говоря, лучше посмотреть в сторону промисов, тогда вам вообще не придется париться из-за пустых значений ошибок (вы обработаете их через .then и .catch).

Не используйте undefined для обозначения валидности

Для примера, ужасная функция:

function toInt(str:string) {
  return str ? parseInt(str) : undefined;
}

может быть написана намного лучше:

function toInt(str: string): { valid: boolean, int?: number } {
  const int = parseInt(str);
  if (isNaN(int)) {
    return { valid: false };
  }
  else {
    return { valid: true, int };
  }
}

JSON и сериализация

В стандарте JSON есть поддержка кодирования null, но нет undefined. При кодировании в JSON объекта, с атрибутом равным null, атрибут будет включён с нулевым значением, в то время как атрибут со значением undefined будет полностью исключён.

JSON.stringify({willStay: null, willBeGone: undefined}); // {"willStay":null}

В результате, базы данных, основанные на JSON могут поддерживать значения null, но не undefined. Поскольку атрибуты со значением null закодированы, вы можете намеренно очистить атрибут, установив его значение в null перед кодированием и передав объект в удаленное хранилище.

Установка значений undefined может сэкономить память и затраты на передачу, поскольку названия атрибутов не будут закодированы. Однако, это может усложнить семантику очистки значений по сравнению с отсутствующими значениями.

Заключительная мысль

Команда TypeScript не использует null : TypeScript coding guidelines и это не вызвало никаких проблем. Дуглас Крокфорд считает, что null - это плохая идея и всем нам лучше использовать undefined.

Как бы то ни было, стиль NodeJS использует null для аргументов Error в качестве стандарта, посколько это означает Что-то в настоящий момент недоступно. Лично я не хочу разрываться между ними двумя, ведь большинство проектов используют библиотеки с разными подходами, и в обоих случаях использую просто == null.