почему _.delay превращает мой e.type из mouseenter в mouseover

Когда я запускаю это событие с помощью backbone.js и пытаюсь отложить вызов функции, событие event.type изменяется с mouseenter на mouseover, журнал консоли выстреливает «mouseenter», а второй журнал - «mouseover», почему преобразование ???

app.newsroomPageElementView = Backbone.View.extend({
 events: {
    'mouseenter .featured-image': 'imageHover',
    'mouseleave .featured-image': 'imageHover'
 },
imageHover: function (e)  {
         Y.log(e.type); // this outputs out mouseenter
        _.delay(function(){ 
         Y.log(e.type); // this outputs mouseover
        }, 500);
    },    
});

это потому, что через 500 миллисекунд моя мышь уже «вошла», поэтому на самом деле это наведение мыши, потому что моя мышь находится над событием, когда оно срабатывает?


person Zuriel    schedule 10.02.2013    source источник
comment
Попробуйте явно передать объект e: _.delay(function (e) { ... }, 500, e);   -  person Šime Vidas    schedule 11.02.2013
comment
Кроме того, попробуйте setTimeout вместо _.delay, чтобы проверить, не вызвано ли такое поведение _.delay (хотя я не понимаю, как это могло быть).   -  person Šime Vidas    schedule 11.02.2013


Ответы (1)


Это происходит потому, что Backbone передает вам ссылку на объект, который затем используется повторно.

Как вы, наверное, знаете, за событием mouseenter следует событие mouseover. У вас нет обработчика для mouseover, поэтому обычно вам все равно.

Когда происходит mouseenter событие, ваш обработчик вызывается с этим объектом e. Это ссылка на некоторый объект в Backbone; вы регистрируете его type, но затем сохраняете ссылку на этот объект в своем delay обработчике.

Затем ваш обработчик событий возвращается, и управление возвращается потоку Javascript. Событие mouseover запускается. Ваш код может игнорировать его, но Backbone продолжает использовать переданный вам объект и помещает в него информацию о событии mouseover.

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

Это должно стать полезным уроком для всех нас. Во-первых, имейте в виду, что JS имеет дело со ссылками на объекты, и, если вы сохраняете объект, созданный чем-то другим, кроме вашего кода, а затем прерываете поток, этот объект может измениться под вами. Точно так же, если у вас есть методы, возвращающие массивы или объекты, знайте, что вы возвращаете ссылку на этот массив или объект ... таким образом, если вызывающий код изменяет содержимое указанного массива или объекта, это может вас испортить; это особенно опасно, когда у вас есть частное поле с общедоступным получателем. Если вы не будете осторожны, вы можете передать ссылку, которая позволяет коду изменять внутреннюю структуру ваших объектов, без вашего ведома!

person Dancrumb    schedule 11.02.2013
comment
Событие mouseenter JavaScript является собственностью Internet Explorer. Из-за общей полезности события jQuery имитирует это событие, чтобы его можно было использовать независимо от браузера.. Я подозреваю, что это повторное использование одного объекта события специфично для смоделированных событий mouseenter и mouseleave. Пометка e дополнительным свойством дает несколько подсказок: jsfiddle.net/ambiguous/J2MFd - person mu is too short; 11.02.2013
comment
Так каков окончательный вердикт? будут ли у этой функции проблемы, о которых мне нужно беспокоиться? Я имею в виду, что примеры с сайта Microsoft показывают, что определенные события mouseenter намного меньше, чем mouseovers, но поскольку эта функция не будет вызываться магистралью до тех пор, пока технически mouseenter, если событие изменится, это не имеет значения, верно? он по-прежнему должен срабатывать только на этом начальном mouseenter, и задержка будет происходить только после успешного mouseenter, что требует, чтобы у меня был mouseleave, прежде чем он сработает. ?? - person Zuriel; 11.02.2013
comment
@ZurielAndrusyshyn: Вы всегда можете клонировать e, чтобы избежать проблем со ссылками. - person mu is too short; 11.02.2013
comment
@ZurielAndrusyshyn: вы правы, что задержка произойдет только после mouseenter (или mouseleave). Как говорит mu, если вам нужно получить доступ к данным события, вы можете клонировать e, когда они впервые появятся. Однако Backbone и Loadash не делают здесь ничего странного с событиями, так что все в порядке. - person Dancrumb; 11.02.2013
comment
jsfiddle.net/Zuriel/HRPDB обновил скрипт обоими примерами из mu и с веб-сайта api jquery. - person Zuriel; 11.02.2013