Чи краще повертати `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;
}

Питання: чи не було б краще повернути сюди "null"?

Я можу передати все, що хочу, назад - очевидно ... Я просто не був впевнений, що найкраще використовувати.

Код, який викликає цю функцію, знає, як боротися з невизначеним (насправді це ніколи не станеться, якщо щось не піде жахливо)

Причина, по якій я задаю це запитання, полягає в тому, що я десь почув щось, що звучало як "Не призначати невизначені змінним" або щось інше - що це ускладнить налагодження. Отже, той факт, що я бачу, що nullпередається назад, говорить мені, що повернення працює - але в основному функціонує схоже на undefined.


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

Mozilla Docs не відповів на моє запитання ... Google теж не відповів: \

Це SO-запитання - було занадто широким для того, що я намагаюся з'ясувати тут.


1
чи не відповідає це ТА Питання ?
warkentien2

8
На мою думку, поверніться null. Залиште undefinedсам JavaScript. Однак "кращого" немає, тому це питання думки.
Фелікс Клінг,

@ warkentien2 Дякую, це було корисно - але мені все ще незрозуміло, що це за умова для повернення з функції отримання.
Джеремі Іглехарт

1
Я читаю nullяк "немає відповідного значення для того, про що ви просите", і undefinedяк "я не можу зрозуміти, про що ви просите".
Марті

@ warkentien2 це питання та те, яке я зв’язав у своїй відповіді, пов’язані, але, схоже, обидва запитують, в чому різниця між ними, а не коли використовувати одне чи інше як повернене значення.
chiliNUT

Відповіді:


37

Я заперечую, що немає найкращого способу, і навіть стандартні функції іноді вибирають те чи інше.

Наприклад:

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

    Звичайні об’єкти мають внутрішній слот [[Prototype]], який визначає, від якого іншого об’єкта вони успадковують. Звичайно, повинен бути спосіб сказати, що об’єкт не успадковується від жодного іншого. У цьому випадку за допомогою "представляється такий об'єкт" null.

  • Object.getOwnPropertyDescriptor

    Очікується повернення дескриптора властивості, тобто об’єкта, що описує властивість (наприклад, значення, записність, перечислюваність та конфігурація). Однак власності може не існувати. У цьому випадку "такого властивості немає" представляється за допомогою undefined.

  • document.getElementById

    Очікується повернення елемента із заданим ідентифікатором. Однак з таким ідентифікатором може не бути елемента. У цьому випадку за допомогою "представляється такий елемент" null.

Тож просто вибирайте те, що вам більше подобається, або вважаєте, що для вашого конкретного випадку це має більше сенсу.


3
після прочитання цього я вирішив запропонувати void 0техніку для майбутніх глядачів цієї відповіді. Я також додав трохи коду, щоб спробувати зробити вашу думку чіткішою. Спасибі за вашу відповідь!
Джеремі Іглехарт

114

Невизначений, як правило, відноситься до того, що ще не отримало значення (поки що). Нуль відноситься до чогось, що остаточно не має значення. У такому випадку я б рекомендував повернути значення null. Зверніть увагу, що функція без вказаного значення повертається неявно повертається невизначеним.

З специфікації 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
Так, невизначеним є значення, яке використовується, коли змінної не присвоєно значення. Чому саме це означає, що ви не повинні повертати невизначену функцію?
Оріоль

1
@Oriol, на мій погляд, оскільки функція void повертається невизначеною, це зарезервоване значення для функцій цього типу, так що при обробці поверненого значення функції null повідомляє мені, що вирішив повернути null, тоді як undefined говорить мені це або вирішив повернути невизначеним, або вирішив нічого не повертати, але я точно не знаю, який. Крім того, якщо я це роблю var x=someFunc();, я навмисно присвоюю значення xa, і волію, щоб воно не пройшло жодних тестів, які вказують, що йому не було (або, можливо, не було присвоєно значення). Just imho
chiliNUT

Це має бути прийнятою відповіддю. Ось як його планували використовувати в специфікації
Цинк

1
Я не так читаю. Я читаю це як: Якщо ви визначаєте змінну, але не ініціалізуєте її, вона натомість матиме початкове значення undefined. Null повинен використовувати програміст, щоб навмисно вказати, що змінна порожня. IMHO undefined ніколи не повинен призначати змінну програмістом, залишайте за допомогою js-движка, щоб використовувати її. Значення терміна "об'єкт" вводить в оману, оскільки в JS навіть примітиви поводяться здебільшого як об'єкти завдяки
автобоксу

1
Так, це має сенс. Чесно кажучи, я не проти використовувати одне над іншим (хоча я вже звик null), поки ви дотримуєтесь одного, але наявність 2 значень для позначення відсутності значення (незалежно від типу) завжди бентежить.
Серхіо Росас

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 "Зверніть увагу, що функція без вказаного значення повернення неявно повертається невизначеною." - це правда, оскільки (function(){ /* code */ })()повертає null у консолі.
Джеремі Іглехарт

@JeremyIglehart Цей код насправді нічого не повертає. А ще це дає undefinedна моїй консолі chrome та firefox.
choz

Добре, я не зрозумів вашу думку. Так, якщо ви нічого не повернете явно, undefined буде повернено неявно. Але чому це важливо?
Oriol

1
@Oriol, я думаю, що @choz намагався сказати (як деякі інші також згадували з цього питання), що якщо я хочу повернутись, undefinedякщо щось інше не повернеться раніше - мені це не потрібно, оскільки поведінка функції за замовчуванням, якщо ви нічого не повертаєте - це повертати невизначеним - вони просто кажуть, що це не потрібно. Далі ... Мені подобається те, що ви сказали про вбудовані функції отримання даних, що повертають значення null. Будь ласка, опублікуйте свою відповідь щодо цього, і я прийму її.
Джеремі Іглехарт,

3

Залежить від того, що вам потрібно робити з поверненою вартістю.

typeof null повертає об'єкт. цей об’єкт має значення undefined

typeof undefined повертає undefined


Особисто я зазвичай використовую null.
Dan

4
"цей об’єкт має значення undefined" Ні, це не є і це не об’єкт, це Null. typeofне обов'язково повертає справжній тип даних значення, він має карту, яка відображає типи даних у мітках і повертає відповідну мітку.
Фелікс Клінг,

Не довіряйте 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як ні.


Я бачу, що ти там робиш - і не можу сказати, що ти помиляєшся - тому що в певному сенсі я думаю, ти міг би зробити це тут, і це було б добре. У мене інший шаблон, який я використовую для виконання цієї операції, яка мені більше подобається, тому що я роблю крок "перевірки" після. Я відчуваю, що це отримує перевірку, змішану з поверненням значення. Ось що я роблю:let getStringOrJSON = value => { try { value = JSON.parse(value); } catch(e) { return value; } return value; }; . Тепер я впевнений, що два повернення могли б оброблятися по-різному, і, можливо, не виграти JS-змагання з гольфу. Це працює.
Джеремі Іглехарт,

1

Перша відповідь правильна. Вони мають теоретично різне значення. Однак не завжди зрозуміло, який вибрати.

Я, як правило, використовую null у своєму розвитку, хоча я думаю, що це абсолютно суб'єктивно.

Я використовую це здебільшого тому, що:

  1. undefined змінна може бути перезаписана у старих браузерах, тому її повернення трохи складніше. Ця сама проблема змушує вас використовувати typeof var === 'undefined'при отриманні результатів функції. посилання

  2. Інші мови, як правило, широко використовують нуль, багато з них навіть не мають невизначеного (наприклад, php). Це дає мені певну послідовність при швидкому обміні мовами.


1

Я думаю, що дуже спірно, що використовувати. Я віддаю перевагу коду, який є семантично максимально точним, тому я думаюundefined доцільним у цьому випадку.

Я розглядаю nullпризначення як значення "змінної, що не має значення". Це на відміну від undefinedзначення "цієї речі взагалі немає"

Як зазначалося в попередній відповіді, повернення undefinedмає проблеми, і це повністю залежить від вас, чи турбує вас це. Мені це не заважало б.


2
Але document.getElementById('iDoNotExist')повертається null, навіть незважаючи на те, що значення наближається до "цієї речі взагалі немає". Якщо це роблять стандартні методи, чому б не OP?
Oriol

@Oriol Мені насправді найбільше подобаються ваші міркування. Будь ласка, опублікуйте відповідь щодо цього, і я прийму його. (Я навіть можу додати кілька редагувань, якщо потрібно)
Джеремі Іглехарт,

Yah @Oriol, ось чому я насправді отримую задоволення від дебатів, навіть на сайтах з питань якості. Дуже добре отримувати зустрічні приклади. І ви надали хороший.
Ryan Laboucane

1

Я б стверджував, що в цьому випадку nullслід повернути.

Якщо розглядати це питання з теоретичної інформатики точки зору , то не визначене , використовується для позначення НЕ термінації / НЕ-обчислюваності (тобто заповнювач для невизначеного точки xу вигляді часткової функції f , яка часто написаний f(x) = ⊥).

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

З огляду на це, необхідне спеціальне завершення сигналізації значення без значущого результату (тобто "немає картки, яку я можу повернути для цього входу"), а це для мене nullнемає undefined.


ПРИМІТКИ:

Ви можете побачити деяку підтримку цього аргументу в деяких інших типізованих мовах, де закінчення без значущого результату виражається за допомогою опційного типу (іноді його також називають типом, що має значення NULL ). Прикладом цього є, можливо, у Хаскелі .

З іншого боку, ми, звичайно, не знаємо, що undefinedнасправді має означати JavaScript. Отже, аналогія з невизначеною дещо напружена. Більше того, оскільки ми завжди хочемо працювати з усіма функціями, це означає, що "ніколи не повертатися undefinedз функції". Що здається дещо суворим, оскільки обмежує використання undefinedвластивостей / змінних, які не були встановлені.

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


-1

Моя особиста думка, згідно з моїм досвідом, полягає в тому, що не використовуйте undefined і null, якщо ви не хочете розбивати свій код. Принаймні я б особисто цього уникав. У Javascript є багато функцій, які повертаються невизначеними, і ми повинні їх використовувати. Але при розробці коду не використовуйте його. Важливо завжди "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

Це ідея. Я весь час намагаюся цього уникати. Тому що a nullабо undefinedможе легко розбити ваш код

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.