关于前端:JavaScript-is-weird-记一些奇奇怪怪的表达式打牢基础

7次阅读

共计 4254 个字符,预计需要花费 11 分钟才能阅读完成。

首先在 https://jsisweird.com/ 这个网站看看到底能对多少题。

记录一下我所不分明的中央。

数字、无穷与 0 互相运算会产生什么?

2 / 0 // Infinity
0 / 0 // NaN
-1 / 0 //-Infinity
Infinity * 0 // NaN

原始类型(根本类型)

根本类型(根本数值、根本数据类型)是一种既非对象也无办法的数据。在 JavaScript 中,共有 7 种根本类型:string,number,bigint,boolean,null,undefined,symbol (ECMAScript 2016 新增)。

留神:
尽管 typeof null === 'object',但 null 也是原始类型。
typeof NaN === 'number',NaN 是原始类型。

The ECMAScript Language Specification explains NaN as a number value that is a IEEE 754“Not-a-Number”value. It might seem strange, but this is a common computer science principle.

There are some odd issues surrounding NaN in JavaScript, however. For instance, this is one of the very few instances where the Object.is function disagrees with triple equal.

NaN === NaN; // -> false
Object.is(NaN, NaN); // -> true

Another such rare instance can be seen in question 24.

This legacy issue was later remedied with the isNaN function.

isNaN(NaN); // -> true

加减运算符产生的强制类型转换到底是返回什么?

是返回对两边的 toString() ? 又或者是 Number() ?

看下 ECMAScript Language Specification 这段话:

总结一下。

对于+ 运算符

  1. 当一边为 string,被辨认为字符串拼接,会优先将另一边转换为 string 类型进行拼接。
  2. 当一边为 援用类型,则两边都转化成字符串进行拼接。
  3. 当一边为 number,另一边为 原始类型,则另一边转换为 number。
  4. 两边都为非 number 且 非 string 的原始类型,先尝试将一边强制转化为 number。
123 + '123' // 123123(规定 1)123 + null  // 123(规定 3)123 + true // 124(规定 3)123 + {}  // 123[object Object](规定 2)

对于 -,*,/ 运算符

在对各种非 number 类型使用数学运算符 (- * /) 时,会先将非 number 类型转换为 number。

1 - true // 0,首先把 true 转换为数字 1,而后执行 1 - 1
1 - null // 1,  首先把 null 转换为数字 0,而后执行 1 - 0
1 * undefined //  NaN, undefined 转换为数字是 NaN
2 * ['5'] //  10,['5']首先会变成 '5' -- 拆箱操作, 而后再变成数字 5

truthy 值

看下这个:

In JavaScript, a truthy value is a value that is considered true when encountered in a Boolean context. All values are truthy unless they are defined as falsy. That is, all values are truthy except false, 0, -0, 0n, "", null, undefined, and NaN.

上面这些都是 truthy 值:

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)

如果操作符右边的运算对象是 truthy 值,则 && 操作符返回操作符左边的运算对象:

true && "dog"
// returns "dog"

[] && "dog"
// returns "dog"

== 操作符的规定

看下 ecma262 第 11 版中对于形象等式比拟(Abstract Equality Comparison)的介绍。

我写了下了每一条规定对应的场景:

/* 类型雷同,的执行全等运算判断 **/
1 == 2 // false
1 == 1 // true

/* 有一边是 undefined 且另一边是 null,返回 true **/
undefined == null // true
null == undefined // true

/* 一边是 string 一边是 number,先将 string 转为 number **/
1 == '1' // true
1 == '1a' // false, '1a' 调用 Number() 会转化为 NaN

/* 一边是 string 一边是 bigint,先将 string 转为 bigint **/
1n == '1' // true
1n == '1a' // false, '1a' 调用 Number() 会转化为 NaN

/* 只有一边是 boolean,先将 boolean 强制转为 number **/
1 == true // true
false == 1 // 

/* 一边是 string, number, symbol 或 bigint,另一边是 Object 援用类型,先将 Object 转为原始值 **/
'1,2,[object Object]' == ['1', 2, {}] // true

/* 一边是  bigint, 另一边是 number **/
/* 如果有一边是 NaN,+Infinity, -Infinity,返回 false,否则比拟数学上的值的大小 **/
+Infinity == 999999999999999999999999999n // false
1 == 1n // true

发现:

  1. number 除了和援用类型比拟外,和其余类型比拟时都是其余类型先转为 number。
  2. NaN 和其余任何类型比拟永远返回 false(包含和它本人)。
  3. 除了 undefined == null 外,这两个值和其余任何类型比拟都为 false
  4. 只有一边是 boolean,先将 boolean 强制转为 number
  5. boolean 外的原始类型和援用类型比拟,先把援用类型转为原始类型。

二进制,八进制,十进制,十六进制和它们的互相运算

参考:MDN Web Docs Numbers and dates。

二进制(binary)

0b0B 结尾,如:

0b01111111100000000000000000000000; // 2139095040

八进制(octal)

  1. 如果前导 0 前面的数字在 $0 \sim 7$ 范畴内,则被解读为八进制;

  2. // 888 parsed as decimal
    const a = 0o10; // ES2015: 8
    const b = 00777; // 510,即 8^0 7 + 8^1 7 + 8^2 7

  3. 0o结尾。

十六进制(Hexadecimal)

0x0X 结尾。

以 10 为底的指数

$n$e$m$ 或 $n$E$m$ 示意 $n \times 10^m$。

1E3   // 1000
2e6   // 2000000
0.1e2 // 10

互相运算

都先转为十进制再运算。

逻辑 && 操作符

The logical AND operator is usually used with Boolean values in if-statements, but it actually returns the value of one of the operands. If the first expression can be converted to true, then it returns the second. Otherwise, it returns the first.

只有第一个表达式为 false,就返回第一个表达式的值;如果第一个为 true,则返回第二个表达式的值。

""&& -0; // ->""
-0 && ""; // -> -0
5 && 3; // -> 3
0 && 3; // -> 0

练习题

1.

[] == ![]

左边先转化为布尔值。因为 [] 是 truthy 值,所以 ![] 是 false。

[] == false,一边为援用类型,一边为布尔类型。只有有一边是布尔,就先将布尔类型转为 number。

[] == 0, 一边为 number 类型(非 boolean 的原始类型),一边为援用类型。则先将援用类型转为原始类型。

'' == 0。一边为 string 类型,一边为 number 类型。则先将 string 转为 number。

0 == 0。则最初为 true

2.

true == "true" 

1 == "true" -> 1 == NaN,则最初为 false

3.

010 - 03
010; // -> 8
03; // -> 3
8 - 3; // -> 5

所以答案为 5。

4.

1/0 > 10 ** 1000

JavaScript treats both of these values as infinite, and infinity is equal to infinity. Learn more about infinities.

1/0; // -> Infinity
10 ** 1000; // -> Infinity
Infinity > Infinity; // -> false

所以答案为 false。

5.

true++

输入 stytaxError。

只能死记上面的值了:

true++; // -> SyntaxError
1++; // -> SyntaxError
"x"++; // -> SyntaxError
null++; // -> SyntaxError
undefined++; // -> NaN
$++; // -> NaN
console.log++; // -> NaN
NaN++; // -> NaN

let _true = true;
_true++;
_true; // -> 2

6.

undefined + false

While false can be converted to a number, undefined cannot.
Number(undefined); // -> NaN
Number(false); // -> 0
NaN + 0; // -> NaN

7.

"" && -0

考查 && 运算符的逻辑。
第一个表达式为 false,间接返回第一个表达式的值。
第一个表达式为 true,则返回第二个表达式的值。

此题第一个表达式为 false,则返回第一个,即 ""

参考

JavaScript 隐式类型转换,一篇就够了!

本文首发于我的集体博客:https://callanbi.top/post/jav… 转载请注明起源

正文完
 0