Подтвердить что ты не робот

Null vs. undefined и их поведение в JavaScript

Итак, после большого аргумента/обсуждения/обсуждения реализации null и undefined в javascript мне хотелось бы, чтобы кто-то объяснял причины внедрения и почему они отличаются в некоторых обстоятельствах. Некоторые конкретные моменты, которые я нахожу тревожными:

  • null == undefined оценивается как true
  • null + 1 равно 1, но undefined + 1 равно NaN
  • if(!null) оценивается как true, а if(null) - false, а null == false - false.

Я прочитал спецификацию, и я знаю, как достигнуты результаты, я ищу парадигмы и причины, которые диктуют это спецификацией. Некоторые из этих пунктов, особенно второй, учитывая первое, чувствуют себя очень несовместимыми.

4b9b3361

Ответ 1

Коротка и сладкая версия заключается в том, что JavaScript был разработан и очень быстро реализован командой Netscape, и в нем были некоторые несоответствия, такие как те, которые вы указали.

Команда Internet Exploder сделала все возможное, чтобы точно скопировать JS, и они проделали чертовски хорошую работу, до такой степени, что несогласования были скопированы. Когда Netscape пошел, чтобы получить JS, стандартизованный как ECMAScript MS, был его частью и в основном сказал, что им не разрешалось изменять стандарт, потому что он нарушил бы старый код (существующая инерция систем). Несоответствия были стандартизированы, и это было так.

Douglas Crockford очень хорошая серия разговоров о некоторых из этих проблем.

Ответ 2

В первую очередь, в то время как множество языков уходит, не имея двух методов для подобной цели, в Javascript они выполняют различные, хотя и частично перекрывающиеся цели. "Почему оба?" был задан здесь раньше, и я нахожу, что этот ответ объясняет это довольно хорошо. TL; DR: Javascript имеет определенные языковые функции, которые генерируют отсутствующие значения в отличие от неинициализированных значений:

  • delete 'd values ​​
  • несуществующие свойства в объекте
  • отсутствующие параметры функции

Что касается кажущихся противоречий в вашем вопросе, они на самом деле довольно легко объясняются спецификацией. (Я считаю, что даже можно утверждать, что объяснение изящно, хотя, вероятно, есть те, кто будет категорически не согласен.)

Адресация каждого из них отдельно:

  • null == undefined оценивается как true

См. этот ответ для лучшего объяснения этого. Короче говоря, абстрактное сопоставление равенства указывает, что они (не строго) равны.


  • null + 1 равно 1, но undefined + 1 равно NaN

Оператор + функционирует как оператор unary + (числовое преобразование) или добавление, но оба направляют аргументы в параметр ToNumber, в котором говорится:

Тип аргумента — Результат
undefined — NaN
Null; +0
Boolean — Результат равен 1, если аргумент истинен. Результат равен +0, если аргумент false.
Номер; Результат равен входному аргументу (без преобразования).

Другими словами null + 1 становится +0 + 1, а undefined + 1 становится NaN + 1, который всегда NaN.


  • if (! null) оценивает значение true и если (null) вычисляется как false, но null == false вычисляется как false.

Как вы знаете, ! является оператором Logical Not, и он выполняет ToBoolean преобразование в выражение. Это тип усечения.

if statement (if (expr)) выполняет неявное логическое сравнение expr. Поэтому взгляните на тип выражения в обоих вышеперечисленных выражениях if:

  • if (!null): expr is !null, который, учитывая результат логического оператора not (!), является булевым.
  • if (null): expr is null, что означает, что никакое преобразование не выполнялось.

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

  • if (!"" == !undefined)= true
  • if ("" == undefined)= false, конечно.

Ответ 3

Их лучше всего рассматривать как совершенно разные объекты, используемые для разных целей:

null используется для "не имеет значения". Он довольно редко используется языком, но часто используется средой-хозяином для обозначения "нет значения". Например, document.getElementById возвращает null для неэксентирующих элементов. Точно так же свойство IE-only onreadystatechange для HTMLScriptElement установлено null, а не undefined, чтобы показать, что, хотя свойство существует, оно в настоящее время не установлено. Обычно рекомендуется использовать null в вашем собственном коде вместо undefined и оставить undefined для следующих случаев:

undefined используется для "даже не установлен или даже не существует". Во многих случаях это "дефолт", например. доступ к свойству undefined (например, onreadystatechange для HTMLScriptElement в браузерах, отличных от IE), возвращаемое по умолчанию значение из методов без операторов return, значение по умолчанию параметров функции при вызове функции с меньшим количеством аргументов, чем это объявляет и т.п.

Таким образом полезно придумать null как "действительное значение", только одно означает что-то особенное. В то время как undefined больше относится к языковому уровню.

Конечно, есть некоторые случаи, когда эти рассуждения не полностью сохраняются; это в основном по наследственным причинам. Но есть разница, и это одно, что имеет смысл.


Что касается ваших болевых точек, в частности, они в основном возникают из-за зла оператора == или типа принуждения:

  • null == undefined: не используйте оператор ==, потому что он по существу является беспорядком правил обратной совместимости, которые казались интуитивными в то время.
  • null + 1 === 1 vs. undefined + 1 === NaN: оператор + выполняет операцию принуждения до Number перед оценкой. И null приводит к 0 (+null === 0), тогда как undefined приводит к NaN (isNaN(+undefined) === true).
  • if (!null), if (null), null == false: если оценивает "правду" или "ложность" своего аргумента, что не имеет никакого отношения к беспорядку правил для ==. null является ложным, а !null является правдивым, но правила для == не позволяют null == false.

Ответ 4

null == undefined действительно оценивает значение true, но null === undefined принимает значение false.

Разница в этих двух утверждениях - оператор равенства. Double-equal в Javascript преобразует два элемента в один и тот же тип перед их сопоставлением; для null == undefined это означает, что null преобразуется в переменную undefined до того, как выполняется сравнение, следовательно, это равенство.

Мы можем продемонстрировать тот же эффект со строками и целыми числами: "12" == 12 - true, но "12" === 12 - false.

Этот пример дает нам более простой способ обсудить ваш следующий момент, добавив один к каждому из них. В приведенном выше примере добавление 1 к целому выражению явно дает 13, но с строкой "12" + 1 дается строка "121". Это имеет смысл, и вы не хотели бы этого по-другому, но с двукратным оператором исходные два значения были указаны как равные.

Урок здесь состоит в том, чтобы всегда использовать оператор тройного равенства, предпочитая двойное равенство, если у вас нет конкретной необходимости сравнивать переменные разных типов.

Ваша последняя точка демонстрирует непостоянный характер null в целом. Это своеобразный зверь, так как любой, кто когда-либо пытался работать с нулевым полем базы данных, скажет вам. У Null есть очень специфическое определение в области информатики, которое реализовано аналогичным образом на нескольких языках, поэтому описанная вами ситуация не является особенной странностью Javascript. Нуль странно. Не ожидайте, что он будет вести себя как альтернативное имя для false, потому что это не работает. Встроенное значение infinity может вести себя так же странно и по аналогичным причинам.

Javascript действительно имеет свою долю странности. Вам может быть интересно прочитать http://wtfjs.com/, в котором есть записи для всей загрузки странных вещей, которые делает Javascript. Довольно многие из них связаны с null и undefined (знаете ли вы, что на самом деле можно переопределить значение встроенного объекта undefined?!), и большинство из них имеют объяснение относительно что на самом деле происходит и почему. Было бы полезно показать вам, почему все работает так, как они делают, и определенно поможет показать вам все, чего нужно избегать! И если ничего другого, это делает хороший интересный читать, чтобы увидеть некоторые из злоупотреблений, которые люди пытались бросить на плохой язык.