Ошибка в IE при ручном вызове обработчика событий, учитывая определенные условия

Введение

  • Обратите внимание: я не ищу решение для кода, а скорее понимаю, почему это может произойти.
  • Ошибка возникает в IE (проверены 7 и 8), но не Firefox, Chrome, Safari.

Описание

При ручном вызове функции, назначенной onclick, IE сбрасывает Error: Object doesn't support this action, если выполняются все следующие условия:

  • Вы вызываете метод напрямую через свойство on[event].
  • Вы не используете .call() или .apply().
  • Вы передаете аргумент (любой аргумент, даже undefined).
  • Вы пытаетесь присвоить возвращаемое значение переменной.

Нарушить любое из этих правил, и вызов завершается успешно.

Сама функция не имеет к этому никакого отношения. Пустая функция дает тот же результат.

код

var elem = document.getElementById('test');  // simple div element.
var result;               // store result returned.

function test_func(){};   // function declaration.
                          // function expression behaves identically.

elem.onclick = test_func; // assign test_func to element onclick.

// DIRECT CALL
test_func();                 // works
test_func( true );           // works
result = test_func();        // works
result = test_func( true );  // works

// DIRECT CALL, CHANGING THE CONTEXT TO THE ELEMENT
test_func.call( elem );                  // works
test_func.call( elem, true );            // works
result = test_func.call( elem );         // works
result = test_func.call( elem, true );   // works ******** (surprising)

// CALL VIA ELEMENT, USING .call() METHOD, CHANGING THE CONTEXT TO THE ELEMENT
elem.onclick.call( elem );                  // works
elem.onclick.call( elem, true );            // works
result = elem.onclick.call( elem );         // works
result = elem.onclick.call( elem, true );   // works ******** ( very surprising)

// CALL VIA ELEMENT
elem.onclick();                 // works
elem.onclick( true );           // works
result = elem.onclick();        // works
result = elem.onclick( true );  // Error: Object doesn't support this action

Резюме

Опять же, мне не нужно решение для кода. Скорее, мне любопытно, есть ли у кого-нибудь представление о том, почему IE реализуется таким образом.

Большое спасибо.


РЕДАКТИРОВАТЬ: Чтобы прояснить одно, ничего с фактической функцией, похоже, не имеет никакого значения. Именование параметров, а не их именование, возврат аргумента, возврат литерала, возврат undefined, все это не имеет эффекта.

Это, вероятно, потому, что функция, кажется, никогда не вызвана. Как я заметил в комментарии ниже, код, ведущий к этому вызову, работает нормально, поэтому он не является проблемой синтаксического анализа. Но когда переводчик добирается до этого, он видит:

Variable + AssignmentOperator + DOMElement + EventHandler + CallOperator + Аргумент

... и выдает ошибку. Никаких манипуляций, я, кажется, не имеет никакого значения. Действительное удаление любого из них, и ошибка исчезает.

Если я помещаю добавленную переменную в середину, которая хранит обработчик, тогда запустите его из переменной, в которой она работает.

var temp = elem.onclick;
result = temp( true );    // works

... но это не должно быть большим сюрпризом, так как это фактически то же самое, что и четвертая версия выше.

Ответы

Ответ 1

Что касается "почему", это было реализовано таким образом, то, по-видимому, ответа не было. Хорошим примером является то, что бывший разработчик IE, изобретатель innerHTML, сталкивается с проблемами с самой innerHTML.

Спросить, почему это также не нужно, потому что

  • Вы не часто вызываете обработчики событий с параметрами явно
  • Вы можете решить проблему (как вы сказали в своем вопросе)

Еще одно замечание - ваша аналогия слишком специфична. Проблема не ограничивается assignment expression, вы можете воспроизвести ее другими типами expressions:

undefined === elem.onclick( true )
typeof elem.onclick( true )
elem.onclick( true ) - 1
alert(elem.onclick( true ))

Ответ 2

Вы пробовали использовать найденные инструкции здесь? Он предлагает использовать такой код:

var fireOnThis = document.getElementById('someID');
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent( 'click', true, true, window, 1, 12, 345, 7, 220, false, false, true, false, 0, null );
fireOnThis.dispatchEvent(evObj);

Ответ 3

Попробуйте использовать некоторую функцию, которая фактически имеет один параметр и фактически возвращает что-то. Посмотрите, вызывает ли это ошибку. Это может иметь какое-то отношение к параметрам и возвращаемому значению функции по умолчанию. Попробуйте и отправьте результаты назад, пожалуйста.

ИЗМЕНИТЬ

Если функция не вызвана, проблема может заключаться в разрешении свойства onclick. Возможно, вы каким-то образом не назовете свою определенную функцию, но код находит какую-то другую сборку в объекте IE, когда вы передаете true как параметр. В любом случае это поведение не соответствует спецификациям, поэтому мы можем назвать его ошибкой. Из этих IE есть много, как вы можете видеть из моих собственных вопросов.

IE 8 абсолютный позиционированный элемент вне проблемы отсечения родительского элемента

Нижняя часть IE8: 0 в позиции: абсолютный ведет себя как позиция: исправлено