雖然現代瀏覽器已高度標準化,但維護舊專案時仍需面對 IE 與 Firefox(Gecko)的差異。本文整理 25 項核心差異與解決方案。
| # | 問題 | IE 行為 | Firefox 行為 | 統一解決方案 |
|---|---|---|---|---|
| 1 | 表單元素存取 | document.form.item() | 不支援 | document.form.elements["name"] |
| 2 | 集合取值語法 | collection("key") | 僅支援 collection["key"] | 統一用方括號 [] |
| 3 | event 物件 | 全域 window.event | 僅事件處理函數參數可用 | 參數傳遞:function(e){ e = e || window.event } |
| 4 | ID 當變數 | 可直接用 idName | 不可 | document.getElementById("idName") |
| 5 | 字串取元素 | eval("idName") | 不可 | document.getElementById(idName) |
| 6 | 變數名衝突 | ID 與變數同名衝突 | 不衝突 | 宣告變數加 var,避免同名 |
| 7 | 滑鼠座標 | event.x / event.y | event.pageX / pageY | event.clientX / clientY 兩者皆支援 |
| 8 | Frame 存取 | ID 或 Name 皆可 | 僅 Name | window.frames["name"] 或 document.getElementById("id").contentWindow |
| 9 | 自訂屬性 | 直接 obj.attr | 需 getAttribute() | 統一用 getAttribute()/setAttribute() |
| 10 | 父節點 | parentElement | parentNode | 統一用 parentNode |
| 11 | childNodes 空白節點 | 不包含 | 包含文字節點 | getElementsByTagName() 避開 |
| 12 | const 關鍵字 | 不支援 | 支援 | 改用 var 或 const 配合 Babel 轉譯 |
| 13 | body 就緒時機 | 解析完才存在 | 標籤讀入即存在 | 統一用 DOMContentLoaded 或 defer |
| 14 | URL 編碼 | 接受 & | 需 & 或 & | JS 中直接用 &,模板用 & |
| 15 | nodeName/tagName | tagName 可能有問題 | 文字節點無 tagName | 用 tagName 並檢查非空 |
| 16 | input.type 唯讀 | 唯讀 | 可修改 | 勿動態修改 type,改用 replaceNode |
| 17 | getElementsByName | 不可取 div | 可取任何元素 | 改用 querySelectorAll('[name="x"]') |
| 18 | 游標手型 | cursor: hand | 不支援 | 標準 cursor: pointer |
| 19 | 半透明 | filter: Alpha(Opacity=50) | 不支援 filter | opacity: 0.5(IE9+),舊 IE 套雙重寫法 |
| 20 | 去除連結虛線框 | blr: expression(...) | 不支援 expression | :focus { outline: none; } |
| 21 | 捲軸顏色 | 支援 scrollbar-* | 不支援 | 放棄自訂捲軸,或用 JS 模擬 |
| 22 | border-width 方向 | 上右下左 | 同上但渲染差異 | 明確寫四個值或分開屬性 |
| 23 | body scroll="no" | 支援 | 不支援 | html { overflow: hidden; } |
| 24 | word-break | 支援 break-all | 不支援(舊版) | word-wrap: break-word + table-layout: fixed |
| 25 | 錨點 name/id | 支援 <a name="x"> | 需 id="x" | 兩者並寫 <a id="x" name="x"> |
if ('querySelector' in document))// 統一事件處理
function addEvent(el, type, fn) {
if (el.addEventListener) el.addEventListener(type, fn, false);
else el.attachEvent('on' + type, fn);
}
// 統一取元素
const $ = (id) => document.getElementById(id);
// 統一事件對象
function fixEvent(e) {
e = e || window.event;
e.target = e.target || e.srcElement;
e.preventDefault = e.preventDefault || function(){ e.returnValue = false; };
e.stopPropagation = e.stopPropagation || function(){ e.cancelBubble = true; };
return e;
}