Почему в JavaScript есть значение null?

116

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

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

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

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

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

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

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

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

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

Christoph
источник
3
Чтобы ответить на ваш последний вопрос: нет, вам не следует устанавливать свойства для undefined.
Shog9
4
«undefined» - это просто переменная в глобальной области видимости с примитивным значением «undefined». Для переменной можно указать другое значение: {undefined = "Hello"; оповещения ( не определенно);} Более надежный способ проверки на неопределенный: {если (TypeOf MyVar === "не определен") предупреждение ( "не определен")}
некоторые
1
См. Раздел 4.3.9 - 12 в ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf для undefined / null и 15.1.1.3 для переменной «undefined» в глобальной области.
некоторые
1
Вы должны либо удалить объект, либо установить для него значение null, если это имеет больший смысл, но не значение undefined.
некоторые
4
In JavaScript, there are two values which basically say 'I don't exist' - undefined and null.Нет, только так undefinedговорит.
Гонки за легкостью на орбите

Ответы:

78

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

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

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

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

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

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

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

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

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

bobince
источник
10
Аргументы можно расширять. Вы можете добавить столько, сколько захотите, и функция потенциально может перебирать и использовать их все. Объектам можно присвоить новое свойство в любое время. Это обе мощные функции, но я подозреваю, что появление исключений, как вы предпочитаете, приведет к большим накладным расходам. ИМО, это того стоит. Я трачу гораздо меньше времени на проверку наличия в JS, чем обычно на приведение в более строгие языковые парадигмы.
Эрик Реппен
Забавно, как принятый ответ на вопрос начинается со слов «на самом деле не в этом вопрос ...»
Филипп
@bobince в ранних версиях JS не было inоператора или hasOwnProperty? Потому что они намного безопаснее, чем obj.hello !== undefinedдля проверки наличия свойства у объекта.
Энди
Неважно, я ответил на свой вопрос. Согласно MDN, они оба были представлены в ES3.
Энди
37

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

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

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

Эдди Паркер
источник
1
Я знаю это null !== undefined- мой вопрос заключался в том, почему возникла необходимость в двух вещах, выражающих одну и ту же смысловую концепцию; Кроме того, в вашей ссылке упоминается, что «null - это объект» - это неправильно, это примитив ...
Кристоф
2
Это не одно и то же семантическое понятие. По крайней мере, для меня существует значительная разница между свойством, которому присвоено нулевое значение, и несуществующим свойством.
Дэниел Шаффер,
Но в том-то и дело, это не одно и то же семантическое понятие. При использовании == Null принудительно подразумевает то же самое, для удобства программиста.
Эдди Паркер
1
@EricElliott: typeofложь - прочтите спецификацию или попробуйте вернуться nullиз конструктора
Кристоф
5
@EricElliott: возвращаемое значение конструктора не имеет ничего общего с ложностью, но с объектной сущностью: если возвращаемое значение является объектом, вернуть его; если это примитив, например nullили 42, отбросьте возвращаемое значение и вместо этого верните вновь созданный объект
Christoph
17

Я не думаю, что есть какая-то причина иметь и то 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должно представлять «небытие». Однако реализация оказалась не такой.

Лэй Чжао
источник
1
Замените undefinedна nullв приведенных выше примерах кода, и все ответы будут одинаковыми. Я не знаю, как это ответить на вопрос. Было ли это означать комментарий к чьему-то ответу?
Эрик Эллиотт
1
@EricElliott Мой ответ на вопрос состоит в том, что нет причин иметь и то nullи другое undefined, потому что единственная причина, по которой многие люди предложили, неверна.
Лэй Чжао
Вы должны отредактировать свой ответ и сказать это на самом деле. Я мог бы проголосовать за, если бы вы дали такой ответ. =)
Эрик Эллиотт
@EricElliott Я думаю, вы правы. Я отредактировал свой ответ. Спасибо!
Лэй Чжао
3
Этот пример на самом деле показывает, что если вы не назначили переменную, она вернется undefined. Но если вы назначили undefinedего, на самом деле undefinedэто не так - он был определен undefinedи имеет ссылку на него. Единственная разница между undefinedи nullзаключается в их использовании и исторической цели. Оба они атомарны.
Алексей Комаров
6

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

EBGreen
источник
6

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

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

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

Джек Райан
источник
Не могли бы вы поделиться этой ролевой игрой?
Майкл
3

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

AnthonyWJones
источник
1
но вы можете использовать его undefinedдля назначения свойств, поэтому этот контракт (только возврат, undfinedесли такого свойства нет) может быть легко нарушен программистом ...
Кристоф,
2
Вы можете , но вы определенно не должны. Undefined используется как очень простая / упрощенная форма исключения в JavaScript - не используйте его как значение и присваивайте его какому-либо свойству! Это сумасшедший человек.
rfunduk
3

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

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

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

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

Steve11235
источник
0

Попробуйте этот пример:

<html>
<head>
    <script type="text/javascript">
        function ShowObjProperties(obj) {
            var property, propCollection = "";

            for(property in obj) {
                propCollection += (property + ": " + obj[property] + "\n");
            }

            alert(propCollection);
        }

        var obj = {
            userid: 3,
            name: 'me!',
            speak: function() { alert('Hi! My name is ' + this.name + ' and my ID is ' + this.userid + '.'); }
        }

        //Shows all properties
        ShowObjProperties(obj);

        //The Speak function is no longer in the list!
        delete obj.speak;
        alert(typeof obj.speak);
        ShowObjProperties(obj);

        //The UserID is still listed, it just has no value!
        obj.userid = null;
        ShowObjProperties(obj);
    </script>
</head>
<body>

</body>
</html>

Я думаю, что здесь есть реальное применение двум различным типам.

EndangeredMassa
источник
А в прототипах, я думаю, это член null или просто undefined.
Кев
но это работает только до тех пор, пока никто не пытается его сломать - если я установлю obj.userid = undefined, он не удастся - см. последнее изменение моего вопроса
Кристоф
0

Все сводится к динамической природе javascripts.

Вещи могут быть неопределенными, чтобы их можно было добавить позже. Возможно, поэтому javascript такой мощный и расширяемый.

Роб Стивенсон-Леггетт
источник
и каким образом это имеет отношение к моему вопросу?
Кристоф
2
Это актуально, потому что отвечает на ваш вопрос. «null» - это своего рода «синглтон», что означает «не имеет значения». "undefined" говорит вам, что что-то ... шокирует, я знаю ... не определено. Это совершенно разные вещи.
rfunduk
0

это важная языковая функция, если вы обертываете свою программу вокруг четной парадигмы 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 и неопределенный сервер очень понятны и предназначены для разных целей. поиск, который не найден в объекте filter_func_pt, который возвращает undefined, означает добавить свойство к возвращаемому объекту как есть, тогда как нулевое значение указывает, что значение должно быть удержано, а не добавлено, и наличие любого истинного значения в этом case представляет функцию, используемую для преобразования значения перед добавлением его в объект ret .

Огненная ворона
источник
Этот пример надуманный и немного бессмысленный. Null вообще не проясняет ваше намерение, а скорее маскирует его. Вы могли бы использовать более явную строку, чтобы прояснить смысл. Например, «удержать» или «убрать», а затем вы также можете более подробно узнать о типе функции и фактически проверить наличие функции.
Эрик Эллиотт
0

null прекрасен

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

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

Почему вы хотите говорить неправильные вещи ?!

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

Об этих вещах принято говорить как о «типах», хотя это не так. Фактически это «категории». Но теперь все кончено.

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

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

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

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

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

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

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

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

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

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

oElement.onclick >> null

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

oElement.innerText >> ""

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

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

Оставайся на морозе и получай удовольствие.

Билл Ящерица
источник
Не портите свои посты, эней. Удалите их (используя кнопку « Удалить» над этим комментарием), если хотите удалить свой вклад.
Майкл Петротта,
кнопки удаления нет - но если вы ее видите - нажмите ее!
0

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

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

Итак, я думаю, имеет смысл иметь тип данных Null.

Документация также упоминается как typeof null // "объект" (не "null" по устаревшим причинам)

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

Вишал Бхандаре
источник