Что лучше - вернуть undefined или null из функции javascript?

98

У меня есть написанная мною функция, которая выглядит примерно так:

function getNextCard(searchTerms) {
  // Setup Some Variables

  // Do a bunch of logic to pick the next card based on termed passed through what I'll call here as 'searchTerms' all of this logic is omitted because it's not important for my question.
  // ...

  // If we find a next card to give, than give it
  if (nextCardFound)
    return nextCardFound;

  // Otherwise - I'm returning undefined
  return undefined;
}

Вопрос: Не лучше ли было бы здесь вернуть «ноль»?

Я могу передать обратно все, что захочу - очевидно ... Я просто не знал, что лучше использовать.

Код, вызывающий эту функцию, знает, как работать с undefined (на самом деле этого никогда не произойдет, если что-то пойдет не так, как надо)

Причина, по которой я задаю этот вопрос, заключается в том, что я где-то слышал что-то вроде «Не назначать неопределенные переменные» или что-то в этом роде - это затруднит отладку. Итак, тот факт, что я вижу, что это nullпередается обратно, говорит мне, что возврат работает, но в основном работает аналогично undefined.


Документация:

Mozilla Docs Не ответил на мой вопрос ... Google тоже не ответил: \

Этот ТАК вопрос - был слишком широким для того, что я пытаюсь понять здесь.

Джереми Иглхарт
источник
1
не отвечает на этот ТАК вопрос ?
warkentien2
8
На мой взгляд, вернемся null. Оставьте undefinedсам JavaScript. Однако «лучше» не бывает, так что это вопрос личного мнения.
Felix Kling
@ warkentien2 Спасибо, это было полезно, но я до сих пор не понимаю, какое здесь соглашение для возврата из функции получения.
Джереми Иглхарт
1
Я читал nullкак «нет подходящей ценности для того, о чем вы просите» и undefinedкак «Я не могу понять, о чем вы просите».
Марти
@ warkentien2 этот вопрос и тот, который я связал в своем ответе, связаны, но оба, кажется, спрашивают, в чем разница между ними, а не когда использовать тот или иной в качестве возвращаемого значения.
chiliNUT

Ответы:

37

Я буду утверждать, что нет лучшего способа, и даже стандартные функции иногда выбирают то или другое.

Например:

  • [[Прототип]]

    У обычных объектов есть внутренний слот [[Prototype]], который определяет, от какого другого объекта они наследуют. Конечно, должен быть способ сказать, что объект не наследуется ни от одного другого. В этом случае «такого объекта нет» передается с помощью null.

  • Object.getOwnPropertyDescriptor

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

  • document.getElementById

    Ожидается, что он вернет элемент с данным идентификатором. Однако элемента с таким идентификатором может не быть. В этом случае «такого элемента нет» передается с помощью null.

Так что просто выберите то, что вы предпочитаете или считаете более подходящим для вашего конкретного случая.

Ориол
источник
3
после прочтения этого я решил предложить void 0технику для будущих зрителей этого ответа. Я также добавил код, чтобы прояснить вашу точку зрения. Спасибо за ваш ответ!
Джереми Иглхарт
114

Неопределенный обычно относится к чему-то, чему еще не было присвоено значение (пока). Null относится к чему-то, что определенно не имеет ценности. В этом случае я бы рекомендовал вернуть null. Обратите внимание, что функция без указанного возвращаемого значения неявно возвращает undefined.

Из спецификации ECMAScript2015

4.3.10 неопределенное значение

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

4.3.12 нулевое значение

примитивное значение, которое представляет преднамеренное отсутствие какого-либо значения объекта

http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-undefined-type

Дальнейшее чтение:

Когда в JavaScript используется значение null или undefined?

чили ОРЕХ
источник
1
Да, undefined - это значение, используемое, когда переменной не было присвоено значение. Почему именно это означает, что вы не должны возвращать undefined в функции?
Oriol
1
@Oriol, на мой взгляд, поскольку функция void возвращает undefined, то есть зарезервированное значение для функций этого типа, так что при обработке возвращаемого значения функции null сообщает мне, что решил вернуть null, тогда как undefined сообщает мне об этом либо решил вернуть undefined, либо решил ничего не возвращать, но я точно не знаю, что именно. Кроме того, если я это делаю var x=someFunc();, я намеренно присваиваю значение xa и предпочел бы, чтобы оно не проходило никаких тестов, которые указывают, что ему не было (или могло не быть) присвоено значение. Just imho
chiliNUT
Это должен быть принятый ответ. Вот как он должен был использоваться в спецификации
Zinc
1
Я так не читаю. Я читал это так: если вы определяете переменную, но не инициализируете ее, вместо этого она будет иметь начальное значение undefined. Программист должен использовать Null, чтобы намеренно указать, что переменная пуста. IMHO undefined никогда не должно назначаться переменной программистом, оставьте его на усмотрение js-движка, чтобы использовать его. Значение термина "объект" вводит в заблуждение, поскольку в JS даже примитивы ведут себя как объекты по большей части из-за автобокса
chiliNUT
1
Да, в этом есть смысл. Честно говоря, я не против использовать одно вместо другого (хотя я больше привык null), пока вы придерживаетесь одного, но наличие двух значений, указывающих на отсутствие значения (независимо от «типа»), всегда сбивает с толку
Серхио Росас,
39

Я дам вам свой личный выбор между ними.

Мой простой вопрос: может ли значение при другом вводе / состоянии / контексте быть определено для чего-то?

Если да, то используйте nullelse use undefined. В более общем плане любая функция, возвращающая объект, должна возвращать, nullкогда предполагаемый объект не существует. Потому что он мог существовать при другом вводе / состоянии / контексте.

nullпредставляет отсутствие значения для данного ввода / состояния / контекста. Это неявно означает, что концепция самого значения существует в контексте вашего приложения, но может отсутствовать. В вашем примере существует концепция следующей карты, но сама карта может не существовать. nullдолжен быть использован.

undefinedнеявно представляет отсутствие смысла этого значения в контексте вашего приложения. Например, если я манипулирую userобъектом с заданным набором свойств и пытаюсь получить доступ к этому свойству pikatchu. Значение этого свойства должно быть установлено равным, undefinedпотому что в моем контексте иметь такое свойство не имеет смысла.

негритян
источник
1
Это так верно для меня. Чистые функции IMO должны возвращаться null, а функции с побочными эффектами должны возвращаться undefined, если думать как функциональный программист.
Джейк
4

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

Рассмотрим этот образец,

function getSomething() {
     // .. do something
     return undefined;
}

function doSomething() {
     // .. I'm not gonna return anything.
}

var a = getSomething();
var b = doSomething();

Результат выше образца a === b, который есть undefined. Разница в том, что вы сохраняете выполнение 1 оператора.

чоз
источник
@Oriol Я имею в виду, undefinedне нужно назначать. Все объявленные переменные без значений уже есть undefined.
choz
@choz & @Oriol - как упоминалось ранее @chiliNUT «Обратите внимание, что функция без указанного возвращаемого значения неявно возвращает undefined». - это правда, потому что (function(){ /* code */ })()в консоли возвращается null.
Джереми Иглхарт
@JeremyIglehart Этот код фактически ничего не возвращает. И еще, он дает undefinedна моей консоли Chrome и Firefox.
choz
Хорошо, я не понял твою точку зрения. Да, если вы ничего не вернете явно, undefined будет возвращено неявно. Но какое это имеет значение?
Oriol
1
@Oriol, я думаю, что @choz пытался сказать (как и несколько других, также упомянутых в этом вопросе), что если я хочу вернуться, undefinedесли что-то еще не вернется раньше - мне не нужно, потому что поведение функции по умолчанию, если вы ничего не возвращаете - это возвращает undefined - они просто говорят, что в этом нет необходимости. Далее ... Мне нравится то, что вы сказали о встроенных функциях получения, возвращающих null. Пожалуйста, опубликуйте свой ответ на этот счет, и я приму его.
Джереми Иглхарт
3

Зависит от того, что вам нужно делать с возвращенным значением.

typeof null возвращает объект. этот объект имеет значение undefined

typeof undefined возвращает undefined

Дэн
источник
Лично я обычно использую null.
Дэн
4
«этот объект имеет значение undefined» Нет, это не так, и это не объект, это Null. typeofне обязательно возвращает истинный тип данных значения, у него есть карта, которая сопоставляет типы данных с метками и возвращает соответствующую метку.
Felix Kling
Не доверяйте typeof, несмотря на свое название, он не сообщает тип значения.
Oriol
2

Вот пример, который undefinedимеет больше смысла, чем null:

Я использую функцию-оболочку, JSON.parseкоторая преобразует исключение в undefined:

// parses s as JSON if possible and returns undefined otherwise
// return undefined iff s is not a string or not parseable as JSON; undefined is not a valid JSON value https://stackoverflow.com/a/14946821/524504
function JSON_parse_or_undefined(s) {
    if ("string" !== typeof s) return undefined

    try {
        const p = JSON.parse(s)
        return p
    } catch (x){}

    return undefined
}

Обратите внимание, что nullэто действительно для JSON, а для этого undefinedнет.

мастерxilo
источник
Я вижу, что вы там делаете, и не могу сказать, что вы ошибаетесь, потому что в некотором смысле я думаю, что вы могли бы сделать это здесь, и это было бы хорошо. У меня есть другой шаблон, который я использую для выполнения этой операции, который мне больше нравится, потому что после этого я делаю шаг «проверки». Я чувствую, что здесь валидация смешивается с возвращением значения. Вот что я делаю: let getStringOrJSON = value => { try { value = JSON.parse(value); } catch(e) { return value; } return value; };. Теперь я уверен, что эти два возврата можно было бы обработать по-разному, и они могли бы не выиграть соревнование по гольфу JS. Оно работает.
Джереми Иглхарт
1

Первый ответ правильный. Теоретически они имеют разное значение. Однако не всегда понятно, что выбрать.

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

Я использую это в основном потому, что:

  1. В старых браузерах переменная undefined может быть перезаписана, поэтому ее возврат немного сложнее. Эта же проблема заставляет вас использовать typeof var === 'undefined'при получении результатов функции. ссылка на сайт

  2. Другие языки, как правило, широко используют null, многие из них даже не имеют undefined (например, php). Это дает мне некоторую последовательность при быстром переключении между языками.

Мацей Папроцки
источник
1

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

Я думаю, что nullприсваивания означают «нулевую переменную». Это в отличие отundefined означает, что "этой вещи вообще нет".

Как указывалось в предыдущем ответе, у возврата undefinedесть проблемы, и вам решать, беспокоит ли это вас. Меня это не беспокоит.

Райан Лабукейн
источник
2
Но document.getElementById('iDoNotExist')возвращается null, хотя по смыслу ближе к «этой вещи вообще нет». Если стандартные методы это делают, то почему не OP?
Oriol
@Oriol Мне больше всего нравятся твои рассуждения. Пожалуйста, отправьте ответ на этот вопрос, и я приму его. (Я мог бы даже добавить несколько правок, если необходимо)
Джереми Иглхарт
Да @Oriol, вот почему я действительно люблю дискутировать, даже на сайтах вопросов и ответов. Очень хорошо получить встречные примеры. И вы предоставили хороший.
Ryan Laboucane
1

Я бы сказал, что в этом случае nullнужно вернуть.

Если рассматривать этот вопрос с теоретической информатики точки зрения , то не определено , используется для обозначения не терминации / не-вычислимости (т.е. заполнитель для неопределенного точки xв виде частичной функции f , которая часто написан f(x) = ⊥).

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

При этом требуется специальное значение, сигнализирующее о завершении без значимого результата (т.е. «нет карты, которую я могу вернуть для этого ввода»), а для меня этого nullнет undefined.


ПРИМЕЧАНИЯ:

Вы можете увидеть некоторую поддержку этого аргумента в некоторых других типизированных языках, где завершение без значимого результата выражается с использованием типа параметра (иногда также называемого типом, допускающим значение NULL ). Примером этого является Maybe в Haskell .

С другой стороны, мы, конечно, не знаем, что undefinedна самом деле должно означать JavaScript. Таким образом, аналогия с undefined несколько неубедительна. Более того, поскольку мы всегда хотим работать с общими функциями, это равносильно тому, чтобы сказать «никогда не возвращаться undefinedиз функции». Это кажется немного строгим, так как это ограничило бы использование undefinedсвойств / переменных, которые не были установлены.

В конце концов, мое личное предпочтение - никогда не возвращаться undefinedтуда, куда я могу вернуться, nullи я также считаю, что это лучшее соглашение о кодировании (потому что, среди прочего, x !== nullоно короче typeof x !== 'undefined').

FK82
источник
-2

Мое личное мнение по моему опыту - не используйте undefined и null, если вы не хотите разрушать свой код. По крайней мере, я бы этого лично избегал. В Javascript есть много функций, которые возвращают undefined, и мы должны использовать их. Но когда вы разрабатываете свой код, не используйте его. Важно всегда "false"хоть что-то вернуть . Например, если у вас есть массив и вы наносите на него карту. Возвращаться [undefined, undefined.....]или просто - нехорошо undefined. Лучше, если вы сохраните тип исходного массива. Пример:

 const mapper:Map <string[],boolean[]>  
['i', 'dont', 'use', 'null or undefined'] -> [false, true, false, true, false]
or ['', dont, '', '', use] 
or al the stuff above and then filter(v => v)
that will keep all undefined and null out

Это идея. Я все время стараюсь этого избегать. Потому что nullили undefinedможет легко привести к сбою вашего кода

rubendmatos1985
источник