Почему в JavaScript есть значение null? - PullRequest
109 голосов
/ 20 января 2009

В JavaScript есть два значения, которые в основном говорят: «Я не существую» - undefined и null.

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

Однажды я подумал, что существует необходимость в null, потому что undefined - это примитивное значение, а null - объект. Это не так, даже если typeof null даст 'object': на самом деле, оба являются примитивными значениями - это означает, что ни undefined, ни null не могут быть возвращены из функции конструктора, так как оба будут преобразованы в пустой объект (один должен выдать ошибку, чтобы объявить ошибку в конструкторах).

Они также оценивают false в логических контекстах. Единственное реальное различие, о котором я могу думать, это то, что один оценивается как NaN, а другой - 0 в числовом контексте.

Так почему же существуют undefined и null, если это просто смущает программистов, которые неправильно проверяют null при попытке выяснить, установлено ли свойство или нет?

Я хотел бы знать, есть ли у кого-нибудь разумный пример, в котором необходимо использовать null, который нельзя выразить с помощью undefined.

Таким образом, по общему мнению, undefined означает «такого свойства не существует», а null означает «свойство существует, но не имеет значения».

Я мог бы согласиться с этим, если бы реализации JavaScript на самом деле обеспечивали такое поведение, но undefined является совершенно допустимым примитивным значением, поэтому его можно легко назначить существующим свойствам, чтобы нарушить этот контракт. Поэтому, если вы хотите убедиться, что свойство существует, вы все равно должны использовать оператор in или hasOwnProperty(). Итак, еще раз: что практического использования для отдельных значений для undefined и null?

Я на самом деле использую undefined, когда хочу сбросить значения свойств, которые больше не используются, но которые я не хочу delete. Должен ли я использовать null вместо этого?

Ответы [ 12 ]

68 голосов
/ 21 января 2009

Вопрос не в том, «почему в JS есть нулевое значение» - в большинстве языков есть какое-то нулевое значение, и обычно оно считается очень полезным.

Вопрос в том, «почему в JS есть неопределенное значение». Основные места, где он используется:

  1. когда вы объявляете 'var x;' но не присваивайте ему, x содержит неопределенное значение;
  2. когда ваша функция получает меньше аргументов, чем объявляет;
  3. при доступе к несуществующему свойству объекта.

'null', безусловно, работал бы так же хорошо для (1) и (2) *. (3) действительно должно немедленно сгенерировать исключение, и тот факт, что он не возвращает вместо этого странного «неопределенного», который позже потерпит неудачу, является большим источником трудностей отладки.

*: вы также можете утверждать, что (2) должно генерировать исключение, но тогда вам нужно будет предоставить лучший, более явный механизм для аргументов по умолчанию / переменных.

Однако в JavaScript изначально не было исключений или какого-либо способа запрашивать объект, если у него есть член под определенным именем - единственный способ был (и иногда остается) получить доступ к члену и посмотреть, что вы получите. Учитывая, что у 'null' уже была цель, и вы, возможно, захотите установить для нее член, потребовалось другое внеполосное значение. Итак, у нас есть «undefined», это проблематично, как вы указали, и это еще одна замечательная «особенность» JavaScript, от которой мы никогда не сможем избавиться.

Я фактически использую undefined, когда хочу сбросить значения свойств, которые больше не используются, но которые я не хочу удалять. Должен ли я вместо этого использовать ноль?

Да. Оставьте 'undefined' в качестве специального значения для сигнализации, когда другие языки могут выдавать исключение.

'null', как правило, лучше, за исключением некоторых интерфейсов IE DOM, где установка значения 'null' может привести к ошибке. Часто в этом случае установка пустой строки имеет тенденцию работать.

37 голосов
/ 20 января 2009

Лучше всего описано здесь , но в итоге:

undefined - это отсутствие типа и значения, а null - отсутствие значения.

Кроме того, если вы делаете простые сравнения = =, вы правы, они получаются одинаковыми. Но попробуйте ===, который сравнивает и тип, и значение, и вы заметите разницу.

16 голосов
/ 18 октября 2012

Я не думаю, что есть какая-либо причина иметь и null, и undefined, потому что единственная причина, по которой многие люди предложили ("undefined означает, что такой переменной / свойства нет"), по крайней мере, недопустима в JavaScript. undefined не может сказать вам, существует ли переменная / свойство или нет.

console.log(foo);               // "ReferenceError: foo is not defined"
                                // foo does not exist
var foo;
console.log(foo);               // "undefined", a different response
console.log(foo === undefined); // "true", but it does exist

var obj = {};
console.log(obj.hasOwnProperty("foo")); // "false", no such property
obj.foo = undefined;
console.log(obj.hasOwnProperty("foo")); // "true", it exists and has the value "undefined"
console.log(obj.foo === undefined);     // "true", but it does exist

obj.bar = "delete me";
obj.bar = undefined;
console.log(obj.hasOwnProperty("bar")); // "true", not actually deleted
delete obj.bar;
console.log(obj.hasOwnProperty("bar")); // "false", deleted

Как видите, проверка foo === undefined не сообщает вам, существует ли foo, а установка obj.bar = undefined фактически не удаляет bar.

Это может быть первоначальное намерение автора JavaScript, что undefined должно представлять "небытие". Однако реализация оказалась не такой.

6 голосов
/ 20 января 2009

Я думаю, что ваш вывод о том, что JavaScript определяет undefined как "такого свойства нет" и null как "свойство не имеет значения", совершенно верен. И в таком динамическом языке, как JavaScript, это очень важное различие. Использование утиной типизации означает, что мы должны различать свойство, не существующее и не имеющее значения. Это наш основной способ получения информации о типе. в статически типизированном языке есть определенное различие между полем, являющимся нулем, и полем, не существующим. В JavaScript это ничем не отличается. Однако он проверяется во время выполнения и может быть изменен до этого времени.

Я должен согласиться с тем, что реализация странная, так как различие часто размыто. Однако я думаю, что в JavaScript важно различие. И возможность назначить undefined необходима.

Я помню, как недавно читал пост в блоге об онлайновой RPG, написанной на JavaScript. В нем использовались примеры, в которых объекты создавались как копии существующих экземпляров, а не как прототипы (классы, функции и т. Д.), А затем изменялись. Это действительно заставило меня понять, насколько мощным может быть undefined при изменении существующих объектов, но я не могу вспомнить, кто его написал.

6 голосов
/ 20 января 2009

Вполне возможно, нужно и то и другое. Например, если вы запрашиваете WMI, вполне возможно иметь свойства, возвращающие класс, которые имеют нулевое значение. Они определены, они просто имеют нулевое значение в то время.

3 голосов
/ 11 апреля 2012

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

Чтобы ответить на ваш вопрос, undefined означает, что значение никогда не задавалось. На практике это обычно указывает на ошибку. Если yourObject.property не определен, это означает, что вы по какой-то причине не установили свойство или я ищу что-то, чего вообще не существует. Это реальная проблема при работе над проектом с более чем одним кодером.

null означает, что "no value" было явно установлено. На практике вы говорите мне что-то о свойстве, возможно, оно не используется в этом контексте или что значение еще не определено.

В Java попытки получить доступ к неопределенному полю всегда приводят к исключению. Фактически, компилятор может быть предупрежден об этом в вашем коде.

3 голосов
/ 20 января 2009

Семантически они означают разные вещи. Тип null имеет ровно одно значение в своем домене, null и свойству может быть присвоено это конкретное значение. Не определено означает явное отсутствие назначенного значения.

0 голосов
/ 17 марта 2018

после прочтения удивительной дискуссии относительно undefined против null, небольшой поиск в Google привел меня в Документацию Mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null это упомянуто - Нуль часто получается в месте, где можно ожидать объект, но ни один объект не является релевантным.

Не похож на шаблон объекта Null https://en.wikipedia.org/wiki/Null_object_pattern

Так что, думаю, имеет смысл иметь тип данных Null.

Документация также упоминается как typeof null // "object" (не "null" по старым причинам)

Не уверен, какие унаследованные причины

0 голосов
/ 09 февраля 2012

ноль - это прекрасно

как и все другие типы Live Script.

cite: в JavaScript есть два значения, которые в основном говорят: «Я не существовать '- неопределенное и нулевое.

Зачем тебе говорить неправильные слова?!

«ноль» - это «пустой объект» , так же как «0» - это «пустой номер» . 0 - это ничто, но оно существует как вещь типа числа. null , конечно, тоже пусто, но "оно есть", и это хорошо определенная вещь Тип объекта .

Обычно говорят об этих вещах как о «типах», когда их нет. На самом деле они являются "категориями". Но теперь все кончено.

Так что придерживайтесь его, чтобы сказать, что «ноль» - это тип объекта без вида. И «ноль» говорит: «Я очень существую [!], Но у меня нет контента моего вида».

Принимая во внимание, что undefined не хватает как Type, так и Kind, где undefined также является его определением Type. Неопределенный тип типа становится его отличительной типологией. Что-то вроде [ничего не существует и как вы определяете «ничто»?] Вопрос.

cite: undefined, ни null может быть возвращено из функции конструктора, так как оба будут конвертером в пустой объект

Вам удалось еще раз сказать неправильную вещь. Конечно, нет, «неопределенный» - это не Объект, это простой Знак, который мы, люди, понимаем; но вопреки этому null есть - и он говорит вам, что: его Тип верен, но искомый Вид не содержится внутри него или, по крайней мере, в данный момент. Приходите к нам позже, когда мы поместим \ назначим какой-нибудь объект в него.

процитируйте: единственное реальное различие, о котором я могу думать, состоит в том, что каждый оценивает NaN, другой к 0 в числовом контексте.

В этом вся суть их основного различия, как упомянуто: undefined - простой знак, и поскольку он состоит из того же «генетического» материала, что и его дальние родственники: строки, [+ undefined] операция преобразует его в NaN, аналогично null, конечно, вместо этого превратится в правильный тип 0 \ Number вместо этого, в отличие от undefined , который превратится в строку (! которая не является пустой) !) и именно поэтому он дает вместо NaN . Где: + undefined >> + "undefined" >> NaN. Поскольку числовой контекст ожидает явное значение.

В то время как логический контекст ожидает ссылку - не находит ничего для преобразования и выдает 'false'.

Давай сейчас прорвемся ...

процитируйте: Итак, еще раз: что практического использования для отдельных значений для undefined и null?

Я постараюсь привести только два эмпирических примера и надеюсь, что хватит

oElement.onclick >> null

// означает - свойство существует; его ожидаемое значение имеет тип: объект , и этот oElement поддерживает событие "onclick"!

oElement.innerText >> ""

// означает - свойство существует; его ожидаемое значение имеет тип: String , что означает, что oElement поддерживает свойство "innerText".

в обоих случаях - если вы получили «undefined», это означает, что свойство не существует; не поддерживается или имеет неправильную (ua vendor) реализацию.

Оставайся морозным и веселись.

0 голосов
/ 25 февраля 2011

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

// a key exists as a placeholder for something
if(obj[name] === null) 
// no key exists int eh hashtable that is in this object
if(obj[name] === undefined)

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

filter_func_pt = {
  date:function(d){ return Math.round(d.getTime()/1000);},
  user: null,
}

function transform(obj){
    var ret = {};
    for( var prop in obj){
       var f = filter_func_pt[prop];
       if(f)
          ret[prop] = f(obj);
       else if(filter_func_pt[prop] === null)
         continue;
       else
         ret[prop] == obj;
    }
  return ret;
}

var a = {
   date: new Date(),
   user: 'sam'
   votes: [23, 41, 55] 
};

var b = transform(a);

/* b = {
 *    date: 1298582417
 *    votes: [23, 41, 55]
 * }
 */

в приведенном выше коде ключевое слово null и сервер undefined очень понятны и предназначены для разных целей. поиск, который не найден в объекте filter_func_pt, который возвращает undefined , означает добавление свойства к возвращаемому объекту как есть, тогда как значение null указывает, что значение должно быть удержано, и не добавляется, и наличие любого истинного значения в этом случае представляет собой функцию, используемую для преобразования значения перед добавлением его в объект ret .

...