JavaScript 中的假值

IT技术 javascript
2021-02-28 01:31:40

今天我遇到了一个有趣的面试问题,这让我有点难受。我被问到假值。所以 undefined、NaN、null、0 和空字符串都被评估为 false。在 JavaScript 中知道这很有用的原因是什么?我唯一能想到的就是不必这样做:

if (mystring === '' || mystring === undefined) { }

我可以做这个:

if (!mystring)

这是唯一有用的应用程序吗?

6个回答

您必须注意的错误值的一个危险问题是检查某个属性是否存在。

假设您要测试新房产的可用性;当此属性实际上可以具有0or值时"",您不能简单地使用以下方法检查其可用性

if (!someObject.someProperty)
    /* incorrectly assume that someProperty is unavailable */

在这种情况下,您必须检查它是否真的存在:

if (typeof someObject.someProperty == "undefined")
    /* now it's really not available */

还要注意,NaN它不等于任何东西,甚至不等于它自己 ( NaN != NaN)。

typeof 检查是不必要的。如果你想检查一个属性是否存在,你通常想知道它是未定义的还是空的。对于该检查,如果(someObject.someProperty == null)。如果您只想检查它是否未定义,请执行 if (someObject.someProperty === undefined)。
2021-04-25 01:31:40
@Angiosperm 在 JavaScript 中,对象无论如何都是动态的,因此没有属性的对象和具有属性设置为的对象之间没有实际区别 undefined
2021-05-01 01:31:40
@Adam:一个缺点:undefined 可能会被覆盖。或使用in运算符:if ("property" in object)
2021-05-02 01:31:40
@Šime Vidas Scenario:我们的应用程序调用某个远程位置以检查资源是否存在。在应用程序的生命周期中,资源的存在是不变的。这种检查可能很昂贵,所以我们要开始缓存调用的结果。让我们将对象的某些属性设置为该调用的结果。现有代码仅检查调用结果是否为“未定义”以决定资源是否存在。为了不必更改我们当前的接口,缓存机制必须检查适当的属性是否实际存在,而不仅仅是未定义。
2021-05-04 01:31:40
但是您可以合法地将属性设置为 undefined,从而破坏此测试。使用 someObject.hasOwnProperty 几乎肯定会更好,并且如果您真的关心该属性是否存在于对象原型链中的任何位置,则递归检查这一点。
2021-05-13 01:31:40

JavaScript 中的“falsey”值有两个不同的问题。

首先是官方的转换方案,即Boolean(x)返回的内容。当 x 为假或 0 或 NaN 或 null 或未定义或 "" 时返回假,否则返回真。这是相同的行为

if (condition) {/*true path*/} else {/*false path*/}

也就是说,如果 Boolean(condition) 会返回 false,则执行 false 路径,否则执行 true 路径。此行为通常用于检查是否定义了属性。但是,这样做并不安全,除非您确定该属性是一个对象或一个数组(如果已定义)。测试属性是否已定义的最安全方法是执行

if (property != null) { /*property is defined*/} 

这确保该属性不为空或未定义。如果您只想确保该属性不是未定义的,请执行

if (property !== undefined) { /*property is not undefined (but may be null)*/ } 

(注意 !== 中的额外 =)。

其次,所有的值都是 == 假的。这是可以强制为 0 的所有内容(这就是 false 被强制为 0 的内容)。这包括所有转换为 false 的值,除了 NaN(它不能 == false,因为它从不 == 任何东西)、null 和 undefined。但它还包括所有在转换为字符串然后转换为数字时等于 0 的对象。例如,这包括转换为字符串时为空字符串 "" 或 "0" 或 "-0" 的所有对象" 或 "+0" 或 "0x00" 或 "000" 或 "0e0" 或 "0.0000"....,例如,

({toString: function() {return "-00.0e000";}}) == false

是真的。有趣的是,这包括空数组,以及仅包含一个返回空或 0 字符串的其他项的数组的任何嵌套,因为呈现为字符串的数组仅显示没有周围括号的内容。那是,

[[[[0]]]] == false; // Because [[[[0]]]].toString() === "0"
[] == false;
[[[""]]] == false;
["0"] == false;
[[({toString: function() {return "0";}})]] == false;

这里描述了计算 == false 的完整算法

这很重要的原因是因为如果您不了解这些规则中的大部分,它可能会导致微妙的、难以发现的错误。最重要的收获可能是它的if (condition)工作原理,并且使用 === 避免了大多数其他疯狂的东西。

了解它在 JS 中的工作原理很重要,因此您不会感到惊讶。不一定只是什么是虚假的,而是什么是真实的以及它们如何相互比较。

一个例子是,'0' 被认为等于 0 和 ==,但它不等于 '' - 尽管 0 是。JavaScript 比较并不总是可传递的。

所以这意味着仅仅因为(foo==bar && bar==fizz)是真的,(foo==fizz)并不总是真的。按照上面的例子,'0'==0,和 0=='',但是 '0'!='' - 因为你在后一个实例中比较字符串,所以它们作为字符串进行比较而不是强制的到数字。

重要的是要知道0评估false以防止做以下事情:

if(str.indexOf('foo'))
@Nick:我认为,重要的是知道,这两个是很重要的,那-1就是truthy和0是falsy。-1那时我可能还没有想过这个案子。在 PHP 中,情况会更严重,因为false如果找不到字符串,则等效函数会返回
2021-04-24 01:31:40
@FelixKling 这是有道理的。顺便提一句。if(str.indexOf('foo') + 1)应该像 expexted(在 JS 中)一样工作,但可读性不高..
2021-04-28 01:31:40
@FelixKling:但是在这种情况下,知道 0 的计算结果为 false 并不重要。当 -1 评估为 false 时,0 也评估为 false 但并不表示没有发现任何内容的事实将成为绊脚石。
2021-05-15 01:31:40
无论如何,这将如何运作?当没有找到任何东西时它返回-1,这不是一个错误的值。
2021-05-15 01:31:40

检测浏览器是否具有特定的预定义对象很有用:

if(!!navigator.geolocation){
  // executes if the browser has geolocation support
}

if(!!document.createElement('canvas').getContext){
  // executes if the browser supports <canvas>
}

说明:navigator.geolocation 是一个对象或未定义。如果它是一个对象,!navigator.geolocation将返回 false,如果它未定义,它将返回 true。因此,要检查浏览器是否启用了地理定位,您需要通过添加另一个!.

我不明白...if (!!foo.bar)和 和有if (foo.bar)什么区别
2021-04-20 01:31:40
使用 Boolean(value) 显式类型转换为布尔值可能更好。它的可读性明显更高,而不是更多的字符。
2021-04-20 01:31:40
@elduderino 不,它会返回true。这 !运算符首先将其操作数转换为布尔值,然后将其切换... 如果 navigator.geolocation 未定义,则将其转换为布尔值 false,然后切换为 true...
2021-04-24 01:31:40
所以如果我做了 if(!navigator.geolocation){ } 并且它是 undefined 那么这会返回 false 吗?
2021-04-29 01:31:40
在这种情况下,没有。!!运营商用于类型转换为布尔值,因此如果你想一个值显式转换为布尔值,可以使用!!value
2021-05-11 01:31:40