Каковы типичные причины, по которым Javascript, разработанный в Firefox, терпит неудачу в IE? [закрытый]
Я разработал некоторые расширенные страницы javascript, которые отлично работают на последних Firefox и Safari. Я пропустил проверку в Internet Explorer, и теперь я нахожу, что страницы не работают на IE 6 и 7 (до сих пор). Скрипты как-то не выполняются, страницы показывают, как будто javascript там не было, хотя некоторый javascript выполняется. Я использую собственные библиотеки с манипуляцией dom, из YUI 2 я использую Yui-Loader и XML-Http-запрос, а на одной странице Я использую "psupload", который зависит от На jQuery.
Я устанавливаю Microsoft Script Editor из Office XP и теперь буду отлаживать. Сейчас я также напишу конкретные тесты.
каковы типичные точки сбоя IE? В каком направлении я могу держать глаза открытыми.
Я нашел эту страницу, которая показывает некоторые различия. на странице: Quirksmode
можете ли вы по своему опыту назвать некоторые типичные вещи, которые я должен искать в первую очередь?
Я также задам больше вопросов здесь для конкретные задачи позже, но сейчас меня интересует ваш опыт, почему IE обычно терпит неудачу в сценариях, которые отлично работают в Firefox
Edit: Спасибо за все эти отличные ответы!
тем временем я адаптировал весь код, чтобы он также работал с Internet Explorer. Я интегрировал jQuery и построил свои собственные классы поверх него. Это была моя основная ошибка, что я не строил все свои вещи на jQuery с самого начала. Теперь Я иметь.
также JSLint мне очень помог.
и многие из отдельных вопросов из разных ответов помогли.
18 ответов
пожалуйста, не стесняйтесь, чтобы обновить этот список, если вы видите какие-либо ошибки/недочеты и т. д.
Примечание: IE9 исправляет многие из следующих проблем, поэтому многое из этого относится только к IE8 и ниже и в определенной степени IE9 в режиме причуд. Например, IE9 поддерживает SVG,<canvas>
, <audio>
и <video>
изначально, однако вы должны включить режим соответствия стандартам для них, чтобы быть доступный.
общие:
-
проблемы с частично загруженными документами: это хорошая идея, чтобы добавить JavaScript в
window.onload
или аналогичное событие, поскольку IE не поддерживает многие операции в частично загруженных документах. разными атрибутами: в CSS, это
elm.style.styleFloat
в IE vselm.style.cssFloat
в Firefox. В<label>
теги это доступ сelm.htmlFor
в IE vselm.for
в Firefox. Обратите внимание, чтоfor
зарезервировано в IE soelm['for']
вероятно, лучше остановить IE от создания исключения.
базовый язык JavaScript:
-
доступ к символам в строках:
'string'[0]
не поддерживается в IE, поскольку это не в исходных спецификациях JavaScript. Использовать'string'.charAt(0)
или'string'.split('')[0]
отметить, что доступ к элементам в массивах значительно быстрее, чем с помощьюcharAt
со строками в IE (хотя есть некоторые начальные расходы приsplit
сначала называется.) запятые перед окончанием объектов: например
{'foo': 'bar',}
не допускаются в IE.
специфические для элемента вопросы:
-
получение
document
из Элемент iframe:-
Firefox и IE8+:
IFrame.contentDocument
(IE начал поддерживать это из версии 8.) -
IE:
IFrame.contentWindow.document
- (
IFrame.contentWindow
относится кwindow
в обоих браузерах.)
-
Firefox и IE8+:
холст: версии IE до IE9 не поддерживают
<canvas>
элемент. IE поддерживает VML однако это аналогичная технология, и explorercanvas смогите обеспечить обертку на месте для<canvas>
элементы для многих операций. Имейте в виду, что IE8 в режиме соответствия стандартам во много раз медленнее и имеет гораздо больше сбоев, чем в режиме причуд при использовании VML.SVG: IE9 поддерживает SVG изначально. IE6-8 может поддерживать SVG, но только с внешние модули с поддержкой только некоторых из этих плагинов Манипуляции с JavaScript.
<audio>
и<video>
: поддерживаются только в IE9.динамическое создание кнопки: IE document.createElement uncheckable. См. также как вы динамически создаете переключатель в Javascript, который работает во всех браузерах? для того, чтобы обойти этот.
встроенный JavaScript в
<a href>
теги иonbeforeunload
конфликты в IE: если есть встроенный JavaScript вhref
частьa
тег (например,<a href="javascript: doStuff()">
тогда IE всегда будет показывать сообщение, возвращенное изonbeforeunload
еслиonbeforeunload
обработчик удаляется заранее. См. также попросите подтвердить при закрытии вкладки.<script>
различия событий тегов:onsuccess
иonerror
не поддерживаются в IE и заменяются IE-специфичнымonreadystatechange
который запускается независимо от того, удалось ли загрузить или не удалось. См. также JavaScript Безумие для получения дополнительной информации.
размер элемента / положение / прокрутка и положение мыши:
-
получение размера/положения элемента: ширина/высота элементов иногда
elm.style.pixelHeight/Width
в IE, а неelm.offsetHeight/Width
, но ни один из них не является надежным в IE, особенно в режиме причуд, и иногда один дает лучший результат, чем другой.elm.offsetTop
иelm.offsetLeft
часто неправильно сообщается, что приводит к неправильному поиску позиций элементов, поэтому всплывающие элементы и т. д. Во многих случаях отключены на несколько пикселей.также обратите внимание, что если элемент (или родитель элемента) имеет
display
ofnone
тогда IE вызовет исключение при доступе атрибуты size / position вместо возврата0
как Firefox делает. -
получить размер экрана (получение видимой области экрана):
-
Firefox:
window.innerWidth/innerHeight
-
IE стандартный режим:
document.documentElement.clientWidth/clientHeight
-
режим совместимости в IE:
document.body.clientWidth/clientHeight
-
Firefox:
-
положение прокрутки документа / положение мыши: этот на самом деле не определен w3c, поэтому он нестандартен даже в Firefox. Чтобы найти
scrollLeft
/scrollTop
наdocument
:-
Firefox и IE в режиме совместимости:
document.body.scrollLeft/scrollTop
-
IE в стандартном режиме:
document.documentElement.scrollLeft/scrollTop
-
Примечание: некоторые другие браузеры использовать
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]; };
для того, чтобы получить позицию курсора мыши,
evt.clientX
иevt.clientY
наmousemove
события дадут положение относительно документа без добавления положения прокрутки таким образом, предыдущая функция должна быть incorporated: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]]; }; };
-
Firefox и IE в режиме совместимости:
выбор/диапазон:
<textarea>
и<input>
выбор:selectionStart
иselectionEnd
не реализованы в IE, и на его месте есть собственная система "диапазонов", см. Также позиция курсора в textarea, в символах с самого начала.-
получение выделенного текста в документ:
-
Firefox:
window.getSelection().toString()
-
IE:
document.selection.createRange().text
-
Firefox:
получение элементов по ID:
-
document.getElementById
оname
атрибут в формах (в зависимости от того, что определено первым в документе), поэтому лучше не иметь разных элементов, которые имеют одно и то жеname
иid
. Это относится к тем дням, когдаid
не был стандартом w3c.document.all
(собственническое IE-специфическое свойство) значительно быстрее, чем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; }; };
проблемы с только для чтения innerHTML:
-
IE делает не поддерживает установка innerHTML
col
,colGroup
,frameSet
,html
,head
,style
,table
,tBody
,tFoot
,tHead
,title
иtr
элементы. Вот функция, которая работает вокруг этого для элементов, связанных с таблицей: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; }; }; };
Также обратите внимание, что IE требует добавления
<tbody>
до<table>
перед добавлением<tr>
s в том, что<tbody>
элемент при создании с помощьюdocument.createElement
, для пример: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
переменной: события DOM не передаются функциям в IE и доступны какwindow.event
. Один из распространенных способов получения события-использовать, например,elm.onmouseover = function(evt) {evt = evt||window.event}
значение по умолчаниюwindow.event
еслиevt
неопределено.ключевые различия кода события: ключевое событие коды сильно различаются, хотя, если вы посмотрите на Quirksmode или JavaScript Безумие, это вряд ли специфично для IE, Safari и Opera снова отличаются.
-
событие Mouse различия: на
button
атрибут в IE-это бит-флаг, который позволяет сразу несколько кнопок мыши:-
слева: 1 (
var isLeft = evt.button & 1
) -
правильно: 2 (
var isRight = evt.button & 2
) -
центр: 4 (
var isCenter = evt.button & 4
)модель W3C (поддерживается Firefox) менее гибка, чем модель IE, только с одной кнопкой, разрешенной сразу с левой стороны как
0
, так как2
и центр1
. Заметьте, что, как Петр-Павел Кох упоминает, это очень контр-интуитивный, как0
обычно означает "нет кнопки".offsetX
иoffsetY
are проблематично и, вероятно, лучше избегать их в IE. Более надежный способ получитьoffsetX
иoffsetY
в IE было бы получить должность относительно расположенного элемента и вычесть его изclientX
иclientY
.Также обратите внимание, что в IE, чтобы получить двойной щелчок в
click
событие, которое вам нужно зарегистрировать какclick
иdblclick
событие функции. Пожары в Firefoxclick
а такжеdblclick
при двойном щелчок, поэтому IE-специфическое обнаружение необходимо иметь такое же поведение.
-
слева: 1 (
-
различия в модели обработки событий: как проприетарная модель IE, так и модель Firefox поддерживают обработку событий снизу вверх, например, если есть события в обоих элементах
<div><span></span></div>
тогда события будут запускаться вspan
затем наdiv
а не порядок, который они связаны, Если традиционный например,elm.onclick = function(evt) {}
был использован.события"захвата" обычно поддерживаются только в Firefox и т. д., что вызовет
div
тутspan
события в порядке сверху вниз. Т. е.elm.setCapture()
иelm.releaseCapture()
для перенаправления событий мыши из документа в элемент (elm
в этом случае) перед обработкой других событий, но они имеют ряд производительности и других проблем, поэтому, вероятно, следует избегать.-
Firefox:
прикрепить:
elm.addEventListener(type, listener, useCapture [true/false])
отключить:elm.removeEventListener(type, listener, useCapture)
(type
например'mouseover'
безon
) -
IE: только одно событие данного типа на элементе может быть добавлено в IE-исключение возникает, если добавлено более одного события того же типа. Также обратите внимание, что
this
относится кwindow
вместо связанного элемента в функциях событий (так менее полезно):прикрепить:
elm.attachEvent(sEvent, fpNotify)
отключить:elm.detachEvent(sEvent, fpNotify)
(sEvent
например'onmouseover'
)
-
-
различия атрибутов событий:
-
остановить события от обработки любым другим прослушиванием функции:
Firefox:
evt.stopPropagation()
IE:evt.cancelBubble = true
-
остановить, например, ключевые события от вставки символов или остановки флажков от проверки:
Firefox:
evt.preventDefault()
IE:evt.returnValue = false
Примечание: только что вернулсяfalse
наkeydown
,keypress
,mousedown
,mouseup
,click
иreset
также предотвратит дефолт. -
получить элемент, который вызвал событие:
Firefox:
evt.target
IE:evt.srcElement
получение элемента, от которого курсор мыши отошел:
evt.fromElement
в IEevt.target
в Firefox, если вonmouseout
событие, в противном случаеevt.relatedTarget
получение элемента, на который переместился курсор мыши:
evt.toElement
в IEevt.relatedTarget
в Firefox, если вonmouseout
событие, в противном случаеevt.target
Примечание:
evt.currentTarget
(элемент, к которому было привязано событие) не имеет эквивалента в IE.
-
проверьте также запятые, такие как эти или подобные, если они есть в вашем коде
var o={
'name1':'value1',
'name2':'value2',
}
последняя запятая (после value2) будет допускаться Firefox, но не IE
Если вы придерживаетесь использования jQuery или YUI, поскольку ваш пост помечен, у вас должны быть минимальные различия между браузерами...вот для чего предназначены фреймворки, чтобы позаботиться об этих кросс-браузерных различиях для вас.
например, посмотрите на страница обхода quirksmode DOM, согласно ему IE не поддерживает большинство вещей...хотя true, фреймворки делают, например IE не поддерживает elem.childElementCount
, но в jQuery: $(elem).children().size()
работает, чтобы получить это значение, в каждом браузер. Вы обнаружите, что в библиотеке есть что-то для обработки 99% неподдерживаемых случаев в браузерах, по крайней мере, со скриптом...с CSS вам, возможно, придется перейти к плагинам для библиотеки, общим примером этого является получение закругленных углов, работающих в IE...поскольку у него нет поддержки CSS для таких.
Если, однако, вы начинаете делать вещи напрямую, например document.XXX(thing)
, тогда вы не в Библиотеке, вы делаете javascript напрямую (это все javascript, но вы получаете точку :), и это может или не может вызвать проблемы, в зависимости от того, насколько пьяна команда IE при реализации этой конкретной функции.
С IE вы с большей вероятностью потерпите неудачу при стилизации, выходящей правильно, чем необработанные проблемы javascript, анимации на несколько пикселей и тому подобное,много больше-так в IE6 конечно.
getElementbyID также будет соответствовать атрибуту name в IE, но не в других браузерах, и IE выберет то, что он найдет первым.
пример:
<script>
var foo = document.getElementById('bar');
</script>
....
<input name="bar" type="text" /> //IE will get this element
<span id="bar"> Hello, World! </span> //FF,Safari,Chrome will get this element
есть много вещей, но одна ловушка, в которую я попадал, заключалась в том, что многие браузеры принимают JSON без кавычек, в то время как ie6 и ie7 этого не делают.
{ name: "Jakob" } // will often work, but not in ie6/ie7
{ "name": "Jakob" } // Better!
редактировать: чтобы уточнить, это только проблема, когда требуется фактический JSON, в отличие от объектного литерала. JSON является подмножеством синтаксиса объектного литерала и подразумевается как формат обмена данными (например, XML), поэтому он предназначен для выбора.
Различная Поддержка JavaScript
IE не поддерживает (большинство) расширений, добавленных в JavaScript с 1.5.
новое в 1.6
- Различными Методами -
indexOf()
,lastIndexOf()
,every()
,filter()
,forEach()
,map()
,some()
-
for each ... in
- выполняет итерацию значений вместо имен свойств.
новое в 1.7
- Реструктуризующее присваивание --
[a,b] = [1,2]
- итераторы и генераторы
-
let
иyeild
новое в 1.8
- Различными Методами -
reduce()
,reduceRight()
- ярлыки для определения функций.
некоторые из этих вещей требуют, чтобы вы указали номер версии JavaScript для запуска под (который сломается в IE), но некоторые вещи, такие как [1,2,3].indexOf(2)
может показаться, что это не так уж важно, пока вы не попытаетесь запустить его в IE
основные различия между JavaScript в IE и JavaScript в современных браузерах(например, Firefox) можно объяснить теми же причинами, что и различия в CSS/(X)HTML кросс-браузере. В то время не было стандарта де-факто; IE/Netscape/Opera воевали за территорию, реализуя большинство спецификаций, но также опуская некоторые, а также делая проприетарные спецификации, чтобы получить преимущества друг над другом. Я мог бы продолжить, но давайте перейдем к выпуску IE8: JavaScript был избегали / презирали в течение многих лет, и с ростом FF и презрением к webcomm, IE решил сосредоточиться в основном на продвижении своего CSS от IE6. И в основном оставил поддержку DOM позади. Поддержка DOM IE8 также может быть IE6, которая вышла в 2001 году....таким образом, поддержка DOM IE почти на десятилетие отстает от современных браузеров. Если у вас есть несоответствия JavaScript, особенно для движка макета, вам лучше всего атаковать его так же, как мы взяли на себя проблемы CSS; таргетинг на этот браузер. НЕ ИСПОЛЬЗОВАТЬ Браузер нюхает, использует обнаружение функций, чтобы вынюхать Ваш браузер / это уровень поддержки DOM.
JScript не является собственной реализацией ECMAScript IE; JScript был ответом IE на JavaScript Netscape, оба из которых появились до ECMAScript.
Что касается атрибутов типа в элементе скрипта, type="text/javascript" является стандартом по умолчанию (по крайней мере, в HTML5), поэтому вам никогда не понадобится атрибут типа, если ваш скрипт не является JavaScript.
As насколько IE не поддерживает innerHTML...innerHTML был изобретен IE и до сих пор не является стандартом DOM. Другие браузеры приняли его, потому что это полезно, поэтому вы можете использовать это кросс-браузер. Что касается динамически изменяющихся таблиц, MSDN говорит: "из-за конкретной структуры, требуемой таблицами,через свойство innerText и innerHTML свойства объектов table и tr доступны только для чтения."Я не знаю, насколько это было верно Изначально, но очевидно, что современный браузеры выяснили это, имея дело со сложностями компоновки таблиц.
Я настоятельно рекомендую прочитать PPK на JavaScript Джереми Кейт DOM Scripting JavaScript: Хорошие Части и Кристиана Хеллмана!--13-->начало JavaScript с помощью сценариев DOM и Ajax чтобы получить сильное представление о JavaScript.
Что касается фреймворков / библиотек, если у вас нет сильного хватайтесь за JavaScript еще, вы должны избегать их. 2 года назад я попал в ловушку jQuery, и хотя мне удалось совершить великолепные подвиги, я ни черта не узнал о кодировании JavaScript должным образом. Оглядываясь назад, jQuery-это злой удивительный инструментарий DOM, но моя неспособность узнать правильные замыкания, прототипическое наследование и т. д. я не только вернул свои личные знания, но и начал работать с огромными успехами, потому что понятия не имел, что делаю.
JavaScript-это язык браузера; Если вы клиентский / интерфейсный инженер, крайне важно, чтобы вы управляли JavaScript. Узел.js приносит JavaScript полный наклон, я вижу огромные шаги, предпринимаемые ежедневно в его развитии; серверный JavaScript будет стандартом в самом ближайшем будущем. Я упоминаю об этом, чтобы еще раз подчеркнуть, насколько важен JavaScript сейчас и будет.
JavaScript собирается сделать больше волн, чем рельсы.
Счастливый Сценариев!
некоторые собственные объекты доступны только для чтения, но не кажутся таковыми (вы можете писать им, но это не имеет никакого эффекта). Например, общий расширенный javascript основан на расширении Element
объект путем переопределения системных методов, скажем, изменения элемента.прототип.appendChild () чтобы сделать больше, чем добавление дочернего узла - скажем, инициализировать его с данными родителя. Это приведет к сбою в IE6-исходный метод будет вызываться на новых объектах вместо нового.
в некоторых браузерах (Я не помню, что сейчас) считают новые строки между тегами HTML текстовыми узлами, а другие-нет. Поэтому childNodes (n), nextSibling (), firstChild () и тому подобное будут вести себя совершенно по-разному.
конечные запятые в массивах и объектных литералах были проблемой, недавно не проверялись (что означает IE8):
var a = [ 1, 2, 3, ];
var o = { a:1, b:2, c:3, };
это вызовет дополнительный код при создании таких структур на стороне сервера.
Я только что нашел один сегодня утром, коллега поставил тег script как:
<script type="application/javascript">
потому что его автозаполнение ide было перед "text / javascript"
но, оказывается, IE просто игнорирует весь скрипт, если вы используете "application / javascript", вам нужно использовать"text/javascript"
Я нашел странную причуду только на днях с Internet Explorer. Я использовал YUI и заменил содержимое тела таблицы (), установив innerHTML
Y.one('#elementId').set('innerHTML', '<tr><td>Column 1</td></tr>');
это будет работать во всех браузерах, кроме IE. Я, наконец, обнаружил, что вы не можете заменить innerHTML таблицы в IE. Мне пришлось создать узел с помощью YUI, а затем добавить этот узел.
var myNode = Y.node.create('<tr><td>Column 1</td></tr>');
Y.one('#elementId').append(myNode);
Это было весело, чтобы разобраться!
дополнительные запятые и отсутствующие запятые были обычной проблемой в IE, пока она работает плавно на FF.
для чего это стоит, я просто наткнулся на эту неприятную проблему в
скажем, у вас есть такой html:
<table><tr><td>some content...</td></tr></table>
и по какой-то причине (у меня был хороший) вам нужно получить весь HTML в таблице до последнего закрытия TR вы можете попробовать что-то вроде этого:
var tableHtml = document.getElementById('thetable').innerHTML;
var fragment = tableHtml.substring(0, tableHtml.lastIndexOf('</tr>'));
вы упомянули jQuery, с которым я менее знаком, но для общей справки, и в частности с прототипом, одна вещь, чтобы следить за зарезервированными словами / именами методов в IE. Я знаю, что меня часто достают такие вещи, как:
someElement.appendChild(new Element('label',{ **for**: someInput.id }).update( someLabelText );
(новый элемент (tagName, propertyHash) - это способ создания новых элементов в Protitype). В IE for:
должно быть 'for':
, потому что for
- это зарезервированное слово. Что имеет полный смысл - но FireFox будет терпеть этот.
еще пример:
someElement.wrap('div').addClassName('someClass')
(том wrap
метод в прототипе обертывает один элемент в другой) -- в IE, на textareas,wrap
- это собственность, и Element.wrap()
должны использоваться вместо methodized версия
эти два примера, которые приходят на ум из моего опыта. Они основаны на прототипе, но основная проблема не в этом: следите за любыми методами / метками/идентификаторами, которые IE считает зарезервированными словами, но FireFox или Safari будут терпеть.
дело в том, что IE не поддерживает JavaScript... Он поддерживает собственную реализацию ECMAScript: JScript... что немного отличается...
С помощью console.log()
для вывода ошибок на консоль ошибок Firefox приведет к сбою ваших скриптов в IE. Нужно помнить, чтобы взять их, когда вы тестируете в IE.