细数 JavaScript 中一些奇怪的概念

472次阅读  |  发布于3年以前

在这篇文章中,我们将介绍一些奇怪的JavaScript概念,有些可能你知道,有些可能你并不清楚。所以请看到最后哦。

Undefined

在非严格模式下,为全局的未定义标识符赋值实际上是可能的(尽管非常不明智!):

// non-strict
function foo() {
  undefined = 2; // really bad idea!
}

foo();
// Strict Mode
function foo() {
  "use strict";
  undefined = 2; // TypeError!
}

foo();

在非严格模式和严格模式下,你都可以创建名称为undefined的局部变量。但是,这又是一个馊主意!

function foo() {
  var undefined = 2;
  console.log(undefined); // 2
}
foo();

非数字(NaN)

你在两个操作数都不是数字(或可以解释执行为以10为基数或以16为基数的常规数字的值)的情况下执行的任何数学运算,都将导致运算失败无法生成有效数字。在这种情况下,你将获得NaN值。

let a = 2 / "foo"; // NaN
typeof a === "number"; // true

换句话说,“非数字的类型是数字!”导致了命名和语义的混淆。

var a = 2 / "foo";
isNaN(a); // true

相当简单!我使用了名为isNaN(..)的内置全局实用程序,它告诉我们值是否为NaN。问题解决了?不,别高兴得太早。

isNaN(..)实用程序有一个致命的缺陷。它似乎试图从字面上理解NaN(非数字)的含义——其工作基本上是“测试传入的东西是非数字还是数字”。但这并不完全准确:

var a = 2 / "foo";
var b = "foo";
a; // NaN
b; //"foo"
window.isNaN(a); // true
window.isNaN(b); // true--ouch!

从字面上看,"foo"显然不是数字,而是一个字符串。但是在执行isNaN("16")后会返回false,因为当javascript进行隐式转换时,它将完美地转换为number。这就是返回false的原因。

无穷大

使用传统编译语言(如C语言)的开发人员可能习惯于看到编译器错误或运行时异常,例如以下除以零的操作:

let a = 1 / 0;

然而,在JS中,这个操作是明确定义的,结果是值Infinity(又名Number.POSITIVE_INFINITY)。如下所示:

var a = 1 / 0; // Infinity
var b = -1 / 0; // -Infinity

不同的0

虽然这可能会让人感到困惑,但JavaScript确实既有正常的零0(又称为正零+0),也有负零-0。在我解释-0存在的原因之前,我们先来看看一下JS是如何处理的。

除了字面上指定为-0之外,负零也可以由数学运算产生。例如:

var a = 0 / -3; // -0
var b = 0 * -3; // -0

让我们再看一些例子:

var a = 0;
var b = 0 / -3;
a == b; // true
-0 == 0; // true
a === b; // true
-0 === 0; // true
0 > -0; // false
a > b; // false

Null

正如我们知道typeof是一个运算符,通过它我们可以像这样检查变量的类型:

typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof 42 === "number"; // true
typeof "42" === "string"; // true
typeof { life: 42 } === "object"; // true

你注意到了吗,我在上面没有涉及到null。因为它很特殊——特别是在与typeof运算符结合时会出现问题:

typeof null === "object"; // true

如果是返回null那很好(而且是正确的!),但是JS中的这个原始错误已经持续了将近20年,而且似乎修复的可能遥遥无期,因为有太多的web内容依赖于其错误行为,以至于修复这个bug会产生更多的bug并破坏很多很多网络软件。

null是唯一一个为falsy但也从typeof检查返回object的原始值。

题外话

什么是falsy值?

falsy(有时写成falsey)值是在布尔上下文中遇到时被认为是false的值。

if (false)
if (null)
if (undefined)
if (0)
if (-0)
if (0n)
if (NaN)
if ("")

什么是truthy值?

在JavaScript中,truthy值指的是在布尔上下文中遇到时被认为是true的值。

if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)

最后,感谢大家的阅读。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8