zoukankan      html  css  js  c++  java
  • js事件相关面试题

    说是面试题,其实也相当于是对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有问题欢迎与我讨论,共同进步。

  • 相关阅读:
    只会写“Hello World”的菜鸟心声
    新的旅程
    生成[1,2,,3,4,5,6,7,8,9]的随机数组?
    计算java集合中自定义对象出现的次数
    iOS https 证书信任漏洞解决办法
    自定义 URL Scheme 完全指南
    Apple移动设备处理器指令集 armv6、armv7、armv7s及arm64
    url schemes格式错误
    给UITapGestureRecognizer添加tag
    iOS GIF 格式动画 图片显示
  • 原文地址:https://www.cnblogs.com/starof/p/6767655.html
Copyright © 2011-2022 走看看