本文來分享一些前端 JavaScript 中離譜的設計,這些設計日常開發遇到的機率可能比較小,而且一旦 在開發中遇到了,大機率只能自認倒黴了。
所以建議朋友們認真閱讀本篇文章,應該能漲不少知識~
學前端的朋友們,看看以下設計你了解過幾個呢?
parseInt(0.0000005)
答案:5
parseInt(0.5);// -> 0
parseInt(0.05);// -> 0
parseInt(0.005);// -> 0
parseInt(0.0005);// -> 0
parseInt(0.00005);// -> 0
parseInt(0.000005);// -> 0
parseInt(0.0000005);// -> 5
parseInt
函式將其第一個參數轉換為字串(如果它還不是字串),然後再轉換為數位。當將 0.0000005 轉換為字串時,會得到以下結果:
String(0.0000005);// -> "5e-7"
然後
parseInt
函式只取該字串的第一個字元,即 5,並將其解析為一個數位。
[] == ![]
答案:
true
[] == ![]
之所以返回
true
,是因為比較過程中發生了隱式的型別轉換。下面來逐步解析:
[]
是一個空陣列,它是真值。![]
是false
,因為當將空陣列強制轉換為布爾值時,它變為true
,然後被否定為false
。因此,比較變成了[] == false
。當比較不同型別時,JavaScript 將嘗試將一個或兩個值強制轉換為相同型別。在這種情況下,它將嘗試將陣列強制轉換為原始值。
一個空陣列,當被強制轉換為原始值時,變成了一個空字串
""
。因此,運算式[] == false
實際上變成了"" == false
。現在,JavaScript 嘗試將布爾值
false
轉換為數位,即0
,運算式就變成了"" == 0
。根據 JavaScript 的規則,當比較一個字串和一個數位時,字串將被強制轉換為數位。因此,
""
被強制轉換為數位後變成了0
。這時比較的就是0 == 0
,結果是true
。
NaN === NaN
答案:
false
在 JavaScript 中,NaN(Not a Number)是一個特殊的值,表示一個非數位的值。然而,當使用 ===(嚴格相等運算子)來比較 NaN 時,會出現一個特殊的情況:NaN 並不等於 NaN。具體來說,NaN === NaN 的結果是 false,盡管兩者都是 NaN。這是因為在 IEEE 754 浮點數標準中,NaN 被定義為不等於任何其他值,包括它自身。
要檢查一個值是否是 NaN,通常使用 isNaN() 函式,但請註意,isNaN() 對於非數位型別的參數(如字串或物件)也可能返回 true,因為它會嘗試將這些參數轉換為數位。更嚴格的檢查方法是使用 Number.isNaN(),它只有在參數確實是 NaN 時才返回 true。
NaN===NaN// false
isNaN(NaN);// true,但這不是最佳方式
Number.isNaN(NaN);// true,這是更好的方式
[1, 2] + [3, 4]
答案:
"1,23,4"
在 JavaScript 中,當嘗試使用 + 運算子來連線兩個陣列,實際上並不會執行陣列的拼接或合並。相反,由於
+
運算子在 JavaScript 中既可以用作加法運算子(對於數位),也可以用作字串連線運算子(對於字串),因此陣列會首先被轉換為字串,然後再進行連線。
陣列到字串的轉換是透過呼叫陣列的
toString()
方法實作的,這通常會生成一個由陣列元素組成的逗號分隔的字串。因此,
[1, 2]
會被轉換為
"1,2"
,而
[3, 4]
會被轉換為
"3,4"
。然後,這兩個字串會被
+
運算子連線起來,得到
"1,23,4"
。所以,
[1, 2] + [3, 4]
的結果是
"1,23,4"
。
如果想要合並兩個陣列,應該使用陣列的
concat()
方法或擴充套件運算子如下所示:
使用 concat() 方法:
const result =[1,2].concat([3,4]);// [1, 2, 3, 4]
使用擴充套件運算子:
const result =[...[1,2],...[3,4]];// [1, 2, 3, 4]
typeof null
答案:
object
。
在 JavaScript 早期版本中,所有值都儲存在 32 位的單元中,每個單元包含一個小的 型別標簽(1-3 bits) 以及當前要儲存的數據。型別標簽共有五種型別:
000: object - 數據型別為 物件。
1: int - 數據型別為 有符號整數。
010: double - 數據型別為 雙精度的浮點數。
100: string - 數據型別為 字串。
110: boolean - 數據型別為 布爾值。
null
的值是機器碼
NULL
指標(指標值是
000
),也就是說
null
的型別標簽也是
000
,和
object
的型別標簽一樣,所以會被判定為
object
。
try...finally
答案:2
(()=>{
try{
return1;
}finally{
return2;
}
})();
在JavaScript中,當在一個函式(包括箭頭函式)的
try
塊和
finally
塊中都有
return
語句時,
finally
塊中的
return
語句會覆蓋
try
塊中的
return
語句。這是因為
finally
塊總是會被執行,無論
try
塊中的程式碼是否成功執行,或者是否丟擲了異常。而且,如果
finally
塊中有
return
語句,那麽這個
return
語句將決定整個函式的返回值。
0.14 * 100
答案:14.000000000000002
0.13*100// 13
0.14*100// 14.000000000000002
0.15*100// 15
0.16*100// 16
在JavaScript中,所有的數位都是以 64 位浮點數形式儲存的,即使它們被聲明為整數。由於二進制無法精確表示所有的十進制小數,因此在進行浮點數運算時,可能會出現精度問題。由於在二進制浮點數表示中,0.14 不能精確表示,因此在進行乘法運算時會出現微小的舍入誤差。一個經典的問題就是 0.1 + 0.2 不等於 0.3。這兩個問題出現的原因是一樣的。
0.1+0.2===0.3// false
0.1+0.5===0.6// true
為了處理這種精度問題,可以使用
Number.EPSILON
和
Math.round
、
toFixed
等方法來比較浮點數或將其格式化為固定小數位數。如果需要精確計算,並且不能容忍這種舍入誤差,可以使用特殊的庫,如
decimal.js
或
bignumber.js
,它們提供了高精度的十進制數運算。
1.toString()
答案:報錯
const num =1;
num.toString()// 1
1.toString();// Uncaught SyntaxError: Invalid or unexpected token
1..toString();// 1
在 JavaScript 中,
1.toString()
會導致一個語法錯誤,因為點號(
.
)在這裏被解析為浮點數的一部份,但緊接著並沒有另一個數位來形成有效的浮點數位面量,所以解析器會丟擲一個
Uncaught SyntaxError: Invalid or unexpected token
錯誤。
然而,當寫
1..toString()
時,情況就不同了。這裏有兩個點號,但第一個點號實際上並不是浮點數的一部份。這是因為 JavaScript 的解析器在遇到連續的點號時會將它們視為一種特殊的語法結構,即第一個點號被視為數位 1 的結尾(盡管在這裏它並沒有實際意義,因為 1 已經是完整的數位),而第二個點號則作為存取物件內容的操作符。
因此,
1..toString()
實際上是這樣被解析的:
數位 1 被解析為一個完整的數位字面量。
由於緊接著有一個點號,但它並沒有跟隨另一個數位來形成浮點數,所以它被解釋為物件內容的存取操作符。
因為 1 在 JavaScript 中是一個原始值,它本身並沒有
.toString()
方法,但是在這裏,由於點號操作符的存在,JavaScript 會嘗試將 1 轉換為一個Number
物件(這是一個稱為裝箱或自動封裝的過程)。一旦 1 被轉換為
Number
物件,就可以呼叫它的.toString()
方法了。
所以,
1..toString()
最終會返回字串 "1",盡管這種寫法在實際編程中並不常見,因為它可能會引起混淆。更常見的做法是直接對數位變量使用
.toString()
方法,也就是上面的第一種寫法。
Math.max() < Math.min()
答案:
true
Math.max()<Math.min()// true
Math.max()// -Infinity
Math.min()// Infinity
在標準的 JavaScript 環境中,
Math.max()
在沒有參數時應該返回
-Infinity
,而
Math.min()
在沒有參數時應該返回
Infinity
。但是,由於
Infinity
總是大於
-Infinity
,所以
Math.max() < Math.min()
返回 true。
9007199254740992 === 9007199254740993
答案:
true
JavaScript 的 Number 型別是基於 IEEE 754 標準 (也稱為 64 位浮點數)實作的,這意味著它有一些限制,特別是關於可以精確表示的數位的範圍和精度。在 IEEE 754 標準中,最大的安全整數(即可以精確表示的最大整數)是
Number.MAX_SAFE_INTEGER
,其值為
9007199254740991
(2 的 53 次方減 1)。
當嘗試使用大於
Number.MAX_SAFE_INTEGER
的整數時,JavaScript 會嘗試將其儲存為一個近似的浮點數,這可能會導致精度損失。在這個例子中,
9007199254740992
和
9007199254740993
都會被轉換為近似的浮點數,但由於精度限制,這兩個數位可能會表示為相同的浮點數值。
因此,如果需要在 JavaScript 中表示大數位時,建議使用字串來儲存大數,以避免精度遺失。
👇🏻 點選下方閱讀原文,獲取魚皮往期編程幹貨。
往期推薦