React.js vs Mailru-loader.js, или Undefined is not a function

в 17:10, , рубрики: Песочница, метки: ,

Недавно, написав небольшой скрипт с использованием библиотеки react.js, столкнулся с довольно странной ошибкой. Суть ошибки заключалась в том, что при использовании event-ов «onChange», «onFocus», «onBlur» через раз все отваливалось с ошибкой «Undefined is not a function».

Так как на странице, с которой подключался скрипт, было море всяких рекламных баннеров и скриптов, источник пришлось искать методом математического тыка. И как ни странно, источником ошибки оказался загрузчик cdn.connect.mail.ru/js/loader.js

Суть ошибки на самом деле проста, хотя и неочевидна на первый взгляд. При добавлении событий на элементы библиотека react.js проверяет браузер пользователя, и если этот браузер IE, то событие добавляется через методы attachEvent/detachEvent, которые естественно ни в каких других браузерах не работают и вызывают ошибку.
При чем же здесь загрузчик от майлру? Открываем код загрузчика и видим следующий код проверки браузера для IE:

mailru.isIE = (function () {
    var tmp = document.documentMode, e, isIE;
    try{document.documentMode = "";}
    catch(e){ };
    isIE = typeof document.documentMode == "number" ? 11 : eval("/*@cc_on!@*/!1");
    try{document.documentMode = tmp;}
    catch(e){ };
    return isIE;
})()

Все вроде бы хорошо и чудесно, и даже закрыто в try/catch, но теперь выполним одну маленькую проверку (без этого загрузчика):

'documentMode' in document

В браузерах, которые не IE, возвращает false, но если выполнить эту же проверку после работы данного подгрузчика, то возвращается true, хотя значение свойства documentMode и равно undefined, но это все таки true.

Следовательно, если вы используете библиотеки (в частности react.js), которые выполняют проверку из примера выше, то вы рискуете потратить определенное количество времени, для того чтобы понять почему ваш браузер всегда определяется как IE, и почему отваливаются элементарные события.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js