说是面试题,其实也相当于是对js事件部分知识点的一个总结。简单内容一笔带过,了解详情我都给出了参考链接,都是之前写的一些相关文章。JavaScript本身没有事件模型,但是环境可以有。

DOM:addEventListener、removeEventListener、dispatchEvent
IE-DOM:attachEvent、detachEvent、fireEvent
jQuery:on、off、trigger

一、描述js里事件的三个阶段

捕获、处于目标阶段、冒泡阶段(IE8以下只支持冒泡)

了解更多可参考:事件流

二、IE和W3C标准 绑定事件的区别?参数分别是什么?以及IE事件对象中的e有什么区别

标准:

/*
参数:
eventName:事件的名字
function:事件处理函数
Boolean:捕获或者冒泡,默认是false冒泡
*/
/*事件对象e作为参数传入*/
addEventListener(eventName,function(e){
},false);

IE8以下

/*
参数:
onEvnet:是事件处理程序的名字,而不是事件名,就是说在事件名前加上on
function:事件处理函数
*/
/*
e=window.event,事件event是window的一个属性
*/
attachEvent(onEventName,function(){
var e=window.event;
})

了解更多可以参考事件处理程序

三、事件代理的原理及优缺点

原理:靠事件冒泡实现的

优点:

  • 大量减少内存占用,减少事件注册
  • 新增子对象时无需再次对其绑定事件,对于动态内容不符尤其适用

缺点:

适用于表格/列表等重复性dom元素,事件代理用不好可能出现事件误判,即本不应该触发事件的元素被绑定了事件

四、手写原生js实现事件代理

要求:兼容浏览器

考点:事件对象e,IE下事件对应的属性名。

重点是要说到target,currentTarget以及IE下的srcElement和this。

三、四2部分具体可参考:事件的典型应用事件代理

五、实现事件模型

核心需求:可以对某一个事件名称绑定多个事件处理函数,然后触发这个事件名称时,依次按照绑定顺序触发相应的事件处理函数。

原理:写一个类或者匿名函数,有两个函数,一个bind,一个trigger,分别实现绑定事件和触发事件。

在bind和trigger函数外层作用域创建一个字典对象,用于存储注册的事件名称和事件处理函数列表。

bind时,如果字典没有则创建一个,key是事件名称,value是数组,里面放着当前注册的响应函数。

如果字段汇总有,那么就直接push到数组中即可。

trigger时调出来依次触发事件响应函数即可。

还有很多细节:

触发响应函数时的上下文应该是什么?【我觉得应该就是谁触发了这个事件处理函数this就是谁,大家有懂的可以评论一下】

触发响应函数的参数列表应该是什么?

如果要求把trigger的参数列表都传到响应函数中还要考虑把arguments对象转化为纯数组才行。

js中自定义事件模型

function Emitter() {
this._listener = {}; //_listener[自定义的事件名] = [所用执行的匿名函数1, 所用执行的匿名函数2]
} //注册事件
Emitter.prototype.bind = function(eventName, funCallback) {
var listenersArr = this._listener[eventName] || []; ////this._listener[eventName]没有值则将listener定义为[](数组)。
listenersArr.push(funCallback);
this._listener[eventName] = listenersArr;
}
//触发事件
Emitter.prototype.trigger = function(eventName) {
//未绑定事件
if (!this._listener.hasOwnProperty(eventName)) {
console.log('you do not bind this event');
return;
}
var args = Array.prototype.slice.call(arguments, 1); ////args为获得除了eventName后面的参数(最后被用作注册事件的参数)
var listenersArr = this._listener[eventName];
var _this = this;
if (!Array.isArray(listenersArr)) return; ////自定义事件名不存在 listenersArr.forEach(function(callback) {
try {
callback.call(_this, args);
} catch (e) {
console.log(e);
}
});
}
//解绑
Emitter.prototype.unbind = function(eventName, callback) {
this._listener.hasOwnProperty(eventName) && delete this._listener[eventName];
callback && callback();
}

测试用例

var emitter = new Emitter();
emitter.bind("selfEvent", function() {
console.log("第一个绑定");
Array.prototype.forEach.call(arguments, function(item) {
console.log(item);
});
});
emitter.bind("selfEvent", function() {
console.log("第二个绑定");
Array.prototype.forEach.call(arguments, function(item) {
console.log(item);
});
});
emitter.trigger('selfEvent', 'a', 'b', 'c');
emitter.unbind('selfEvent', function() {
console.log("解除绑定");
});
emitter.trigger('selfEvent', 'a', 'b', 'c');

运行结果

六、事件广播(dispatchEvent)

dispatchEvent是js的事件触发器,事件触发器就是用来触发某个元素下的某个事件。

可以自定义事件,通过触发器触发。

<p id="pElement">事件被触发后文字变红</p>

<script>
var pElement=document.getElementById("pElement"); var event=new Event('selfEvent');
pElement.addEventListener('selfEvent', function (e) {
alert(e.type); //selfEvent
this.style.color="red";
},false);
pElement.dispatchEvent(event); </script>

如果初始化自定义事件时需要添加一些额外的数据,可以用CustomEvent构造函数。

var event=new CustomEvent('lxyEvent',{'detail':'liuxiaoyan'});  //detail属性值即自定义数据
pElement.addEventListener('lxyEvent', function (e) {
alert(e.type+ e.detail);
this.style.color="red";
},false);
pElement.dispatchEvent(event);

参考:

2016十家公司前端面试小记

MDN create_and_trigger_events

http://www.cnblogs.com/pcd12321/p/5223347.html

http://www.cnblogs.com/1wen/p/5640997.html

本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/6767655.html有问题欢迎与我讨论,共同进步。

js事件相关面试题的更多相关文章

  1. js 事件相关 事件处理 封装 事件封装 DOM 0 2 3 级事件

    1.绑定 function(element, type, handler){        if (element.addEventListener) {            element.add ...

  2. javascript 事件相关使用总结01

    javascript 事件相关使用总结01 这里总结一下js事件相关的经验. addEventLinstener()介绍 注册事件最基础的函数是这个 target.addEventListener(t ...

  3. js 事件对象相关笔记

    事件对象     event就是一个事件对象 写到我们的监听函数的括号里面 当形参来看     事件对象只有有了事件才存在,他是系统给我们自动创建的 不需要我们传递参数     事件对象是我们事件的一 ...

  4. JS—事件对象

    在触发DOM上的某个事件时,会产生一个事件对象event.这个对象中包含着所有与事件有关的信息.包括导致事件的元素,事件的类型以及其他与特定事件相关的信息. 举例鼠标操作导致的事件对象中,会包含鼠标位 ...

  5. JS事件对象与事件委托

    事件对象 包含事件相关的信息,如鼠标.时间.触发的DOM对象等 js默认将事件对象封装好,并自动的以参数的形式,传递给事件处理函数的第1个参数,如下: document.getElementsByTa ...

  6. 三言两语之js事件、事件流以及target、currentTarget、this那些事

    厉害了我的哥--你是如此简单我却将你给遗忘   放假前再看某文档,里边提到两个我既熟悉又陌生的概念target.currentTarget,说他熟悉我曾经看到过这两个事件对象的异同处,说他陌生吧?很不 ...

  7. js 事件大全

    Js事件大全一般事件 事件 浏览器支持 描述onClick IE3|N2|O3 鼠标点击事件,多用在某个对象控制的范围内的鼠标点击onDblClick IE4|N4|O 鼠标双击事件onMouseDo ...

  8. JS事件

    JS事件:  声明:为了事件对象event跨浏览器兼容: var oEvent==ev||event;      所以在下面用到 event 的地方都用 oEvent 代替  1)doucument的 ...

  9. JS事件模型小结

    三种事件模型:原始事件模型(DOM0),DOM2事件模型,IE事件模型: 不同点: 事件程序的注册(给HTML元素所对应的JS对象绑定事件) 事件传播的过程 事件模型的注册: 一.原始事件模型(没有兼 ...

随机推荐

  1. css重要属性之辩

    一.relative 1)与兄弟 relative对absolute 1.限制left/top/right/bottom定位 2.限制z-index层级: 3.限制在overflow下 relativ ...

  2. Java Reference 源码分析

    @(Java)[Reference] Java Reference 源码分析 Reference对象封装了其它对象的引用,可以和普通的对象一样操作,在一定的限制条件下,支持和垃圾收集器的交互.即可以使 ...

  3. 一些关于Canny边缘检测算法的改进

    传统的Canny边缘检测算法是一种有效而又相对简单的算法,可以得到很好的结果(可以参考上一篇Canny边缘检测算法的实现).但是Canny算法本身也有一些缺陷,可以有改进的地方. 1. Canny边缘 ...

  4. Linux环境Perl链接MS Sql Server数据库

    1.下载相关软件 unixODBC.freetds和DBD-ODBC ①.Linux系统的ODBC unixODBC-2.3.4.tar.gz ( http://www.unixodbc.org) ② ...

  5. Spring:利用PerformanceMonitorInterceptor来协助应用性能优化

    前段时间对公司产品做性能优化,如果单依赖于测试,进度就会很慢.所以就通过对代码的方式来完成,并以此来加快项目进度.具体的执行方案自然就是要知道各个业务执行时间,针对业务来进行优化. 因为项目中使用了S ...

  6. spring+mybatis之声明式事务管理初识(小实例)

    前几篇的文章都只是初步学习spring和mybatis框架,所写的实例也都非常简单,所进行的数据访问控制也都很简单,没有加入事务管理.这篇文章将初步接触事务管理. 1.事务管理 理解事务管理之前,先通 ...

  7. MCMC(四)Gibbs采样

    MCMC(一)蒙特卡罗方法 MCMC(二)马尔科夫链 MCMC(三)MCMC采样和M-H采样 MCMC(四)Gibbs采样 在MCMC(三)MCMC采样和M-H采样中,我们讲到了M-H采样已经可以很好 ...

  8. HANA CDS与ABAP CDS

    如果你在网络或者SCN上面搜索CDS,即SAP的Core Data Services,你会很容易地找到类似“Core Data Services(CDS)是一个在SAP HANA中用于定义和消费富语义 ...

  9. 【C语言】浅谈可变参数与printf函数

    一.何谓可变参数 int printf( const char* format, ...); 这是使用过C语言的人所再熟悉不过的printf函数原型,它的参数中就有固定参数format和可变参数(用& ...

  10. js获取url中的参数方法

    直接调用函数即可,函数如下: function getURLParam(name) { return decodeURIComponent((new RegExp('[?|&]' + name ...