ChatGPT解决这个技术问题 Extra ChatGPT

从 javascript 函数返回 `undefined` 或 `null` 更好吗?

我有一个我写的函数,它基本上看起来像这样:

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”会更好吗?

我可以将任何我想要的东西传回去 - 显然......我只是不确定什么是最好的使用。

调用此函数的代码知道如何处理 undefined(除非出现可怕的错误,否则它实际上永远不会发生)

我问这个问题的原因是我在某处听到一些听起来像“不要将未定义的变量分配给变量”之类的东西 - 这会使调试变得更加困难。因此,我可以看到 null 被传回的事实告诉我返回正在工作 - 但基本上功能类似于 undefined

文档:

Mozilla Docs 没有回答我的问题...谷歌也没有:\

This SO Question - 对于我在这里试图弄清楚的内容来说太宽泛了。

SO Question没有回答吗?
在我看来,返回 null。将 undefined 留给 JavaScript 本身。但是,没有“更好”,所以这是一个见仁见智的问题。
@warkentien2 谢谢,这很有帮助 - 但我仍然不清楚从 getter 函数返回的约定是什么。
我将 null 理解为“您所要求的内容没有适当的价值”,而 undefined 理解为“我无法计算出您所要求的内容”。
@warkentien2 这个问题和我在回答中链接的问题是相关的,但似乎都在问它们之间有什么区别,而不是何时使用其中一个或另一个作为返回值。

C
Community

未定义通常是指尚未分配值(尚未)的事物。 Null 指的是绝对没有价值的东西。在这种情况下,我建议返回 null。请注意,没有指定返回值的函数会隐式返回 undefined。

来自 ECMAScript2015 规范

4.3.10 undefined value original value 当一个变量没有被赋值时使用的值 4.3.12 null value 原始值,表示有意不存在任何对象值

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

进一步阅读:

When is null or undefined used in JavaScript?


是的, undefined 是未为变量赋值时使用的值。为什么这意味着您不应该在函数中返回 undefined ?
@Oriol,在我看来,由于 void 函数返回未定义,这是该类型函数的保留值,因此在处理函数的返回值时, null 告诉我它决定返回 null,而 undefined 告诉我它要么决定返回未定义,要么决定不返回任何东西,但我不确定是哪个。此外,如果我正在执行 var x=someFunc();,我是故意分配 xa 值,并且宁愿它不通过任何表明它没有(或可能没有)被分配值的测试。只是恕我直言
这应该是公认的答案。这就是它打算在规范中使用的方式
我不是这样读的。我将其解读为:如果您定义了一个变量但不对其进行初始化,那么它将具有未定义的初始值。程序员应该使用 Null 来有意地指示变量为空。恕我直言,程序员永远不应将 undefined 分配给变量,将其留给 js 引擎使用它。术语“对象”值具有误导性,因为在 JS 中,由于自动装箱,即使是原语在很大程度上也表现得像对象
是的,这是有道理的。公平地说,我不介意使用一个而不是另一个(尽管我更习惯 null),只要你坚持使用一个,但有 2 个值表示没有价值(无论“类型”是什么)总是令人困惑
K
KenBuckley

我将为您提供我个人在两者之间进行选择的自以为是的方式。

我的简单问题是:给定另一个输入/状态/上下文的值是否可以定义为某些东西?

如果答案是肯定的,则使用 null,否则使用 undefined。更一般地,当预期对象不存在时,任何返回对象的函数都应返回 null。因为它可能存在给另一个输入/状态/上下文。

null 表示给定输入/状态/上下文的价值缺失。它隐含地意味着值本身的 concept 存在于您的应用程序的上下文中,但可能不存在。在您的示例中,存在下一张卡片的概念,但卡片本身可能不存在。应该使用 null

undefined 隐含地表示该值在您的应用程序上下文中没有意义。例如,如果我操作具有给定属性集的 user 对象并尝试访问属性 pikatchu。此属性的值应设置为 undefined,因为在我的上下文中,拥有这样的属性没有任何意义。


这对我来说很真实。当像函数式程序员一样思考时,IMO 纯函数应该返回 null,而具有副作用的函数应该返回 undefined
默认的JS函数不是和这个冲突的吗?例如,当我使用 find 函数时,它会在未找到任何值时返回 undefined。但是当我输入其他内容时,它可能会返回一些内容,对吧?
O
Oriol

我会争辩说没有最好的方法,甚至标准函数有时也会选择其中一种。

例如:

[[Prototype]] 普通对象有一个 [[Prototype]] 内部槽,它决定了它们从哪个其他对象继承。当然,必须有一种方法可以说一个对象不继承自任何其他对象。在这种情况下,“没有这样的对象”使用 null 表示。

Object.getOwnPropertyDescriptor 期望返回一个属性描述符,即描述一个属性(例如值、可写性、可枚举性和可配置性)的对象。但是,该属性可能不存在。在这种情况下,“没有这样的属性”使用 undefined 表示。

document.getElementById 期望返回具有给定 ID 的元素。但是,可能没有具有该 ID 的元素。在这种情况下,“没有这样的元素”使用 null 表示。

因此,只需选择您喜欢或认为对您的具体情况更有意义的任何内容。


reading this 之后,我决定向此答案的未来观众推荐 void 0 技术。我还添加了一些代码来尝试使您的观点更清楚。谢谢您的回答!
这里很重要 - 另一个完美的例子是 Array.prototype.find()
D
Dan

取决于您需要对返回值做什么。

typeof null 返回一个对象。该对象的值为 undefined

typeof undefined 返回 undefined


我个人通常使用null。
“那个对象的值是 undefined” 不,它不是,它不是一个对象,它是 Null。 typeof 不一定返回值的真实数据类型,它具有将数据类型映射到标签并返回相应标签的映射。
不要相信 typeof,尽管它的名字并不能说明值的类型。
c
choz

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
@JeremyIglehart 该代码实际上不返回任何内容。否则,它会在我的 chrome 和 firefox 控制台上提供 undefined
好的,我不明白你的意思。是的,如果你没有显式返回任何东西, undefined 将被隐式返回。但为什么这很重要?
@Oriol,我认为@choz 想说的是(正如其他一些人在这个问题上也提到的那样),如果我想返回 undefined 如果其他东西没有更早返回 - 我不需要因为函数的如果您不返回任何内容,则默认行为是返回 undefined - 他们只是说这不是必需的。此外......我喜欢你所说的关于返回 null 的内置 getter 函数。请张贴您的答案,我会接受。
我仍然更喜欢显式返回 undefined,因为它记录了代码的意图。否则,当我看到一个不返回任何内容的函数时,我不得不问自己编写它的开发人员是否只是忘记了返回某些内容。
m
masterxilo

这是一个示例,其中 undefinednull 更有意义:

我对 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 高尔夫比赛。有用。
F
FK82

我认为在这种情况下,应该返回 null

如果您从理论计算机科学的角度考虑这个问题,那么 undefined 用于表示 non-termination/non-computability(即partial function f 的未定义点 x 的占位符,通常写成 f(x) = ⊥)。

但是,getNextCard 似乎能够计算下一张卡片(如果存在),并且如果没有下一张卡片也能够计算。换句话说,函数是 total,因为它对每个输入都终止。

话虽如此,需要一个特殊值 表示终止而没有有意义的结果(即“我无法为该输入返回任何卡”),这对我来说是 null 而不是 undefined

笔记:

您可以在其他一些类型化语言中看到对该参数的一些支持,其中使用 option type 表示没有有意义结果的终止(有时也称为 可空类型)。 Haskell 中的 Maybe 就是一个例子。

另一方面,我们当然不知道 JavaScript 中的 undefined 真正应该是什么意思。因此,与 undefined 的类比有点勉强。此外,由于我们总是希望使用全部函数,这相当于说“永远不要从函数返回 undefined”。这似乎有点严格,因为它会将 undefined 的使用限制为尚未设置的属性/变量。

最后,我个人的偏好是从不返回 undefined,我可以返回 null,我还认为这是更好的编码约定(因为除其他外,x !== nulltypeof x !== 'undefined' 短)。


C
Community

第一个答案是对的。它们在理论上具有不同的含义。但是,并不总是很清楚该选择哪个。

我倾向于在我的开发中使用 null 尽管我认为这完全是主观的事情。

我使用它主要是因为:

未定义的变量可能会在旧浏览器中被覆盖,因此返回它有点复杂。同样的问题迫使您在获取函数结果时使用 typeof var === 'undefined' 。链接 其他语言倾向于广泛使用 null,其中很多甚至没有 undefined(例如 php)。在语言之间快速切换时,这给了我一种一致性。


R
Ryan Laboucane

我认为使用什么是非常值得商榷的。我更喜欢语义上尽可能准确的代码,因此我认为 undefined 在这种情况下是合适的。

我认为 null 赋值意味着“一个变量设置为空”。这与 undefined 相反,意思是“这东西根本不存在”

正如先前的答案所指出的,返回 undefined 有问题,这完全取决于您是否会打扰您。它不会打扰我。


但是 document.getElementById('iDoNotExist') 返回 null,尽管其含义更接近于“这东西根本不存在”。如果标准方法可以做到,为什么不使用 OP?
@Oriol 我其实最喜欢你的推理。请发布此效果的答案,我会接受。 (如果需要,我什至可以添加一些编辑)
是的@Oriol,这就是我真正喜欢辩论的原因,即使在问答网站上也是如此。获得反例真的很好。你已经提供了一个很好的。
另一方面,如果数组不包含搜索值,则 array.find() 返回 undefined。这不是一致的,我同意。