最初叫 Mocha → LiveScript → JavaScript。Netscape 與 Sun 合作,為行銷蹭 Java 熱度改名。**兩者無任何語言層面關係**。ECMAScript 才是標準名稱。
typeof null === "object" —— 遠古 Bug 成標準typeof null; // "object" (非 "null")
**原因**:JS 初版 (1995) 32 位系統,值以 32 位儲存,低 3 位存型別標籤 (000 = 物件)。null 代表空指標 (全 0),被誤判為物件。修正會破壞既有網站,故保留至今。
**正確判斷 null**:val === null 或 Object.is(val, null)。
NaN !== NaN —— IEEE 754 規範NaN === NaN; // false
NaN == NaN; // false
Object.is(NaN, NaN); // true (ES6)
**原因**:NaN 代表「非數值」狀態,非具體值,兩個「非數值」不具備同一性。
**檢測方法**:Number.isNaN(val) (ES6,不轉型) 或 val !== val (唯一不等於自身的值)。
// 無 var/let/const 直接賦值 → 建立全域屬性
x = 10; // window.x = 10 (瀏覽器環境)
// 迴圈變數洩漏
for (i = 0; i < 3; i++) { ... } // i 變全域
**解決**:嚴格模式 "use strict"; (ES5) 禁止隱式全域;**模組化** (ESM) 預設嚴格、頂層 this 為 undefined;**IIFE/區塊作用域** (let/const) 隔離變數。
歷史鏈:Mosaic → Netscape (Mozilla/1.0) → IE 偽裝 Mozilla/1.22 (compatible; MSIE 2.0) 為通過伺服器 UA 檢測 → 所有瀏覽器跟進偽裝 Mozilla。
**現代對策**:**特性偵測** (Feature Detection) 替代 UA 嗅探。使用 navigator.userAgentData (Client Hints API) 或庫 ua-parser-js。
var obj = {
name: "Obj",
method: function() { console.log(this.name); }
};
var fn = obj.method;
fn(); // "Obj" ? 不!非嚴格模式 this=window → undefined;嚴格模式 this=undefined → TypeError
// 正確綁定
fn.call(obj); // 顯式綁定
obj.method(); // 隱式綁定 (調用位置決定)
var bound = fn.bind(obj); // 硬綁定 (ES5)
**箭頭函數** (ES6) 無 this,捕獲外層詞法作用域 this,解決回調地獄。
JS 數值全為 IEEE 754 雙精度浮點數 (Number)。位運算 (| & ^ ~ << >>) 會:轉 32 位有號整數 → 運算 → 轉回浮點。
**效能**:現代引擎 (V8, SpiderMonkey) 對熱點代碼優化極好,但頻繁轉換仍有開銷。
**適用場景**:旗標位運算、快速取整 ~~x / x | 0、顏色值運算。**不適用**:一般算術、大整數 (用 BigInt)。
| 值 | 型別 | 語意 | 轉布林 |
|---|---|---|---|
undefined | undefined | 變數聲明未賦值 / 缺失參數 / 無回傳函數 | false |
null | object (Bug) | 刻意表示「無物件」 | false |
NaN | number | 數學運算失敗 | false |
"" | string | 空字串 | false |
0 / -0 | number | 零值 | false |
false | boolean | 邏輯假 | false |
document.all | object | 宿主物件,歷史遺留 (類陣列) | false |
**建議**:語意明確時用 null (預期物件)、undefined (未初始化);避免混用。
0.1 + 0.2; // 0.30000000000000004
0.2 + 0.4; // 0.6000000000000001
**原因**:二進制浮點無法精確表示十進制小數 (如 0.1 = 0.0001100110011... 循環)。
**解決方案**:
Math.round((0.1+0.2)*100)/100 或庫 decimal.js。Number.EPSILON (ES6) 比較近似相等:Math.abs(a-b) < Number.EPSILON。// 1. return 後換行 → 插入分號,導致回傳 undefined
function foo() {
return
{ a: 1 };
}
foo(); // undefined
// 正確
function foo() {
return { a: 1 };
}
// 2. 以 [ 或 ( 開頭的行,前一行無分號會被合併
var x = 1
[1,2,3].forEach(...); // TypeError: Cannot read property 'forEach' of undefined (1[1,2,3] = 1,2,3 逗號運算符)
// 3. 模板字串標籤函數
tag`template` // 正確
tag
`template` // 錯誤:視為 tag(`template`),但換行導致 ASI?實際不插入,因模板字串不觸發 ASI
**最佳實踐**:**始終書寫分號**,配合 ESLint semi: ["error", "always"] 強制檢查。Prettier 自動格式化統一風格。
Object.is 替代 === 比較 NaN/±0。JavaScript 的「怪癖」多源於早期設計妥協與向後相容承諾。深入理解底層機制,配合現代工具鏈,即能寫出安全、可維護的高質量代碼。