如果您发现任何错误/遗漏等,请随时更新此列表.
Note: IE9修复了以下许多问题,因此很多问题只适用于IE8及以下版本,在一定程度上IE9处于怪癖模式.例如,IE9本机支持SVG、<canvas>
、<audio>
和<video>
,但是必须enable standards compliance mode才能使用它们.
##一般信息:
Problems with partially loaded documents: It’s a good idea to add your JavaScript in a window.onload
or similar event as IE doesn’t support many operations in partially loaded documents.
Differing attributes:在CSS中,IE是elm.style.styleFloat
,Firefox是elm.style.cssFloat
.在<label>
个标签中,for
属性在IE中用elm.htmlFor
访问,而在Firefox中用elm.for
访问.请注意,IE中保留了for
,因此elm['for']
可能是阻止IE引发异常的更好方法.
##Base JavaScript language:
Access characters in strings: 'string'[0]
isn’t supported in IE as it’s not in the original JavaScript specifications. Use 'string'.charAt(0)
or 'string'.split('')[0]
noting that accessing items in arrays is significantly faster than using charAt
with strings in IE (though there's some initial overhead when split
is first called.)
IE中不允许Commas before the end of objects:例如{'foo': 'bar',}
.
##要素具体问题:
Getting the document
of an IFrame:
- Firefox and IE8+:
IFrame.contentDocument
(IE开始支持此from version 8.)
- IE:
IFrame.contentWindow.document
- (
IFrame.contentWindow
refers to the window
in both browsers.)
Canvas: Versions of IE before IE9 don't support the <canvas>
element. IE does support VML which is a similar technology however, and explorercanvas can provide an in-place wrapper for <canvas>
elements for many operations. Be aware that IE8 in standards compliance mode is many times slower and has many more glitches than when in quirks mode when using VML.
SVG: IE9本机支持SVG.IE6-8可以支持SVG,但只有external plugins个支持JavaScript操作的插件.
<audio>
and <video>
: are only supported in IE9.
Dynamically creating radio buttons: IE<;8有一个错误,使得用document.createElement
创建的单选按钮不可选中.另请参见How do you dynamically create a radio button in Javascript that works in all browsers?,了解解决此问题的方法.
Embedded JavaScript in 101 tags and 102 conflicts in IE:如果a
标记的href
部分(例如<a href="javascript: doStuff()">
)中嵌入了JavaScript,IE将始终显示onbeforeunload
返回的消息,除非事先移除onbeforeunload
处理程序.另请参见Ask for confirm when closing a tab.
<script>
tag event differences: onsuccess
and onerror
aren't supported in IE and are replaced by an IE-specific onreadystatechange
which is fired regardless of whether the download succeeded or failed. See also JavaScript Madness for more info.
##元素大小/位置/滚动和鼠标位置:
- Getting element size/position:在IE中,元素的宽度/高度有时是
elm.style.pixelHeight/Width
而不是elm.offsetHeight/Width
,但在IE中两者都不可靠,尤其是在"怪癖"模式下,有时一个比另一个效果更好.
elm.offsetTop
and elm.offsetLeft
are often incorrectly reported, leading to finding positions of elements being incorrect, which is why popup elements etc are a few pixels off in a lot of cases.
还要注意的是,如果一个元素(或该元素的父元素)的值为display
或none
,那么IE在访问大小/位置属性时会引发异常,而不是像Firefox那样返回0
.
Get the screen size(获取屏幕的可视区域):
- Firefox:
window.innerWidth/innerHeight
- IE standards mode:
document.documentElement.clientWidth/clientHeight
- IE quirks mode:
document.body.clientWidth/clientHeight
Document scroll position/mouse position: This one is actually not defined by the w3c so is non-standard even in Firefox. To find the scrollLeft
/scrollTop
of the document
:
Firefox and IE in quirks mode: document.body.scrollLeft/scrollTop
IE in standards mode: document.documentElement.scrollLeft/scrollTop
NOTE:其他一些浏览器也使用pageXOffset
/pageYOffset
.
function getDocScrollPos() {
var x = document.body.scrollLeft ||
document.documentElement.scrollLeft ||
window.pageXOffset || 0,
y = document.body.scrollTop ||
document.documentElement.scrollTop ||
window.pageYOffset || 0;
return [x, y];
};
为了获得鼠标光标的位置,mousemove
事件中的evt.clientX
和evt.clientY
将给出相对于文档without adding the scroll position的位置,因此需要结合前面的函数:
var mousepos = [0, 0];
document.onmousemove = function(evt) {
evt = evt || window.event;
if (typeof evt.pageX != 'undefined') {
// Firefox support
mousepos = [evt.pageX, evt.pageY];
} else {
// IE support
var scrollpos = getDocScrollPos();
mousepos = [evt.clientX+scrollpos[0], evt.clientY+scrollpos[1]];
};
};
## Select /范围:
##Getting elements by ID:
document.getElementById
还可以在表单中引用name
属性(取决于文档中首先定义的属性),因此最好不要使用具有相同name
和id
的不同元素.这可以追溯到id
不是w3c标准的时代.document.all
(a proprietary IE-specific property)比document.getElementById
快得多,但它还有其他问题,因为它总是将name
置于id
之前.我个人使用了这段代码,并进行了额外的判断,以确保:
function getById(id) {
var e;
if (document.all) {
e = document.all[id];
if (e && e.tagName && e.id === id) {
return e;
};
};
e = document.getElementById(id);
if (e && e.id === id) {
return e;
} else if (!e) {
return null;
} else {
throw 'Element found by "name" instead of "id": ' + id;
};
};
##Problems with read only innerHTML:
IE不需要设置col
、colGroup
、frameSet
、html
、head
、style
、table
、tBody
、tFoot
、tHead
、title
和tr
个元素的innerHTML.下面是一个与表相关的元素相关的函数:
function setHTML(elm, html) {
// Try innerHTML first
try {
elm.innerHTML = html;
} catch (exc) {
function getElm(html) {
// Create a new element and return the first child
var e = document.createElement('div');
e.innerHTML = html;
return e.firstChild;
};
function replace(elms) {
// Remove the old elements from 'elm'
while (elm.children.length) {
elm.removeChild(elm.firstChild);
}
// Add the new elements from 'elms' to 'elm'
for (var x=0; x<elms.children.length; x++) {
elm.appendChild(elms.children[x]);
};
};
// IE 6-8 don't support setting innerHTML for
// TABLE, TBODY, TFOOT, THEAD, and TR directly
var tn = elm.tagName.toLowerCase();
if (tn === 'table') {
replace(getElm('<table>' + html + '</table>'));
} else if (['tbody', 'tfoot', 'thead'].indexOf(tn) != -1) {
replace(getElm('<table><tbody>' + html + '</tbody></table>').firstChild);
} else if (tn === 'tr') {
replace(getElm('<table><tbody><tr>' + html + '</tr></tbody></table>').firstChild.firstChild);
} else {
throw exc;
};
};
};
Also note that IE requires adding a <tbody>
to a <table>
before appending <tr>
s to that <tbody>
element when creating using document.createElement
, for example:
var table = document.createElement('table');
var tbody = document.createElement('tbody');
var tr = document.createElement('tr');
var td = document.createElement('td');
table.appendChild(tbody);
tbody.appendChild(tr);
tr.appendChild(td);
// and so on
##Event differences:
Getting the event
variable: DOM events aren't passed to functions in IE and are accessible as window.event
. One common way of getting the event is to use e.g.
elm.onmouseover = function(evt) {evt = evt||window.event}
which defaults to window.event
if evt
is undefined.
Key event code differences:个关键事件代码差异很大,但如果你看Quirksmode或JavaScript Madness,这几乎不是IE特有的,Safari和Opera又不同了
Mouse event differences: IE中的button
属性是位标志,它允许同时使用多个鼠标按钮:
- Left: 1 (
var isLeft = evt.button & 1
)
- Right: 2 (
var isRight = evt.button & 2
)
- Center: 4 (
var isCenter = evt.button & 4
)
The W3C model (supported by Firefox) is less flexible than the IE model is, with only a single button allowed at once with left as 0
, right as 2
and center as 1
. Note that, as Peter-Paul Koch mentions, this is very counter-intuitive, as 0
usually means 'no button'.
offsetX
and offsetY
are problematic and it's probably best to avoid them in IE. A more reliable way to get the offsetX
and offsetY
in IE would be to get the position of the relatively positioned element and subtract it from clientX
and clientY
.
Also note that in IE to get a double click in a click
event you'd need to register both a click
and dblclick
event to a function. Firefox fires click
as well as dblclick
when double clicking, so IE-specific detection is needed to have the same behaviour.
Differences in the event handling model:专有IE模型和Firefox模型都支持自下而上处理事件,例如,如果<div><span></span></div>
的两个元素中都有事件,那么事件将在span
then和div
中触发,而不是使用传统元素(例如elm.onclick = function(evt) {}
)时它们绑定的顺序.
"Capture" events are generally only supported in Firefox etc, which will trigger the div
then the span
events in a top down order. IE has elm.setCapture()
and elm.releaseCapture()
for redirecting mouse events from the document to the element (elm
in this case) before processing other events, but they have a number of performance and other issues so should probably be avoided.
Firefox:
Attach: elm.addEventListener(type, listener, useCapture [true/false])
Detach: elm.removeEventListener(type, listener, useCapture)
(type
is e.g. 'mouseover'
without the on
)
IE: Only a single event of a given type on an element can be added in IE - an exception is raised if more than one event of the same type is added. Also note that the this
refers to window
rather than the bound element in event functions (so is less useful):
Attach: elm.attachEvent(sEvent, fpNotify)
Detach: elm.detachEvent(sEvent, fpNotify)
(sEvent
is e.g. 'onmouseover'
)
Event attribute differences:
Stop events from being processed by any other listening functions:
Firefox: evt.stopPropagation()
IE: evt.cancelBubble = true
Stop e.g. key events from inserting characters or stopping checkboxes from getting checked:个
Firefox: evt.preventDefault()
IE: evt.returnValue = false
Note: Just returning false
in keydown
, keypress
, mousedown
, mouseup
, click
and reset
will also prevent default.
Get the element which triggered the event:
Firefox: evt.target
IE: evt.srcElement
如果是onmouseout
事件,IE中的Getting the element the mouse cursor moved away from: evt.fromElement
在Firefox中是evt.target
,否则是evt.relatedTarget
如果是onmouseout
事件,IE中的Getting the element the mouse cursor moved to: evt.toElement
在Firefox中是evt.relatedTarget
,否则是evt.target
Note: evt.currentTarget
(事件绑定到的元素)在IE中没有类似功能