网易2017内推笔试题

要求:

  请实现下面的自定义事件Event对象的接口,功能见注释(测试1)

  该Event对象的接口需要能被其他对象拓展复用(测试2)

     //测试1
Event.on('test',function(result){
console.log(result);
});
Event.on('test',function(){
console.log('test');
});
Event.emit('test','hello world'); //输出'hello world' 和 'test'
//测试2
var person1 = {};
var person2 = {};
Object.assign(person1, Event);
Object.assign(person2, Event);
person1.on('call1',function(){
console.log('person1');
});
person2.on('call2',function(){
console.log('person2');
});
person1.emit('call1'); //输出'person1'
person2.emit('call2'); //没有输出
person1.emit('call1'); //没有输出
person2.emit('call2'); //输出'person2' var Event = {
//通过on接口监听事件eventName
//如果事件eventName被触发,则执行callback回调函数
on:function(eventName, callback){
//你的代码
},
//触发事件 eventName
emit:function(eventName){
//你的代码
}
};
  • Object.assign(target, ...sources)  可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。

这里有篇解决的……但是没看明白http://blog.daraw.cn/2016/08/02/javascript-event-emitter/

还是牛客高手多

         var Event = {
on: function(eventName, callback){
this[eventName] = this[eventName] || new Array();
this[eventName].push(callback);
}, emit: function(eventName){
var params = arguments.length>1 ? Array.prototype.slice.call(arguments,1) :[];
if(this[eventName]){
Array.prototype.forEach.call(this[eventName],function(arg){
arg.apply(this,params);
});
}
}
}

以上的方法实现过程中,遇到一些问题……

  1) 一开始想茬了,以为this[eventName]可以写作this.eventName,然而输出结果总是不对。然后才想到,this.eventName等于是调用了名为'eventName’的属性,而不是把eventName代表的字符串传给this的属性。所以失败了。

  2)一开始以为Array.prototype.slice/forEach可以写作Array.方法名,但是会报错。所以应该是只能通过prototype调用call/apply

  3)一开始没有理解这道题的意思。其实指的是:Event中的on绑定事件,而emit执行事件。一开始以为触发事件的代码:Event.emit('test','hello world'); 是传入了两个参数,一次传入test,一次传入hello world。其实完全想错了……很明显,'test’是一个eventName,是在test绑定的事件里传入参数hello world.而之所以输出hello world与test,是因为test绑了两个事件,一个是有参数的输出参数,一个是没有参数的输出test。所以这里是事件绑定而非赋值。

  4)关于Object.assign(). 其定义是这样的:

Object.assign(target, ...sources)

Properties in the object will be overwritten by properties in the sources if they have the same key.  Later sources' properties will similarly overwrite earlier ones.

The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters. Therefore it assigns properties versus just copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters. For copying property definitions, including their enumerability, into prototypesObject.getOwnPropertyDescriptor() and Object.defineProperty() should be used instead.

Both String and Symbol properties are copied.

In case of an error, for example if a property is non-writable, a TypeError will be raised, and the targetobject remains unchanged.

Note that Object.assign() does not throw on null or undefined source values.

  即:将来自一个或多个源对象中的值复制到一个目标对象。

    此函数返回目标对象。

    仅可枚举自有属性从源对象复制到目标对象。

    可使用此函数合并或克隆对象。

    null 或 undefined 源被视为空对象一样对待,不会对目标对象产生任何影响。

  【以下是我的渣翻译】这里意思是说:对象中的属性会被源中的属性覆盖,后面的属性会被前面的覆盖。

  这种方法只会从源对象中复制可枚举的和自己的属性到一个目标对象。然后返回目标对象。

  如果要复制属性定义,包括其可枚举性,应该使用Object.getOwnPrototypeDescriptor()和Object.defineProperty()

  5)牛客网上答题的大神更新了答案,把this复制给一个变量self, var self = this,然后其后的this都用self代替,是【考虑到了参数及this作用域的改进版本】。但是这里并不理解,既然在这个函数里,this和self都指向一样啊?为何要这么做呢?

    我大概明白了……在函数里调用this可能会引发各种奇怪的问题,因为this的指向并不一定总是你想要指的this。但是用self应该也不恰当,因为“You should avoid self as there is a window.self object and you could end up using that accidentally if you forget to declare your own self var”——应该避免self因为有一个window.self对象。所以这里我改成了that。于是代码写作:

         var Event = {
on: function(eventName, callback){
if(!this[eventName]){
this[eventName] = [];
}
this[eventName].push(callback);
},
emit: function(eventName){
var that = this;
var params = arguments.length>1 ? Array.prototype.slice.call(arguments,1) : [];
if(that[eventName]){
Array.prototype.forEach.call(that[eventName],function(arg){
arg.apply(self,params);
});
}
}
}

js:实现自定义事件对象接口的更多相关文章

  1. js的自定义事件

    js中的事件是js的一大技术点,说白了就是操作dom树的唯一途径. 关于事件无非两种绑定方式: document.getElementById('xxx').onclick = function(){ ...

  2. JS中的事件&对象

    一.JS中的事件 (一)JS中的事件分类 1.鼠标事件 click/dblclick/onmouseover/onmouseout 2.HTML事件 onload/onscroll/onsubmit/ ...

  3. (转)js原生自定义事件的触发dispatchEvent

    1. 对于标准浏览器,其提供了可供元素触发的方法:element.dispatchEvent(). 不过,在使用该方法之前,我们还需要做其他两件事,及创建和初始化.因此,总结说来就是: 1 2 3 d ...

  4. js跨浏览器事件对象、事件处理程序

    项目中有时候会不用jquery这么好用的框架,需要自己封装一些事件对象和事件处理程序,像封装AJAX那样:这里面考虑最多的还是浏览器的兼容问题,原生js封装如下:var EventUtil={ //节 ...

  5. JS中的事件(对象,冒泡,委托,绑定)

    - 事件,是文档或浏览器窗口中发生的一些特定的交互瞬间,JS与HTML之间的交互是通过事件实现的 对于web应用来说,有下面这些代表性事件:点击事件,鼠标移动,按下键盘等等 - 事件,是用户和浏览器之 ...

  6. js中获取事件对象的方法小结

    原文地址:http://jingyan.baidu.com/article/d8072ac4594d6cec95cefdac.html 事件对象 的获取很简单,很久前我们就知道IE中事件对象是作为全局 ...

  7. 和我一起理解js中的事件对象

    我们知道在JS中常用的事件有: 页面事件:load: 焦点事件:focus,blur: 鼠标事件:click,mouseout,mouseover,mousemove等: 键盘事件:keydown,k ...

  8. js事件处理、事件对象

    事件类型分类: 1 添加在html结构中的事件 <div id="div1" onclick="alert('append click event in html' ...

  9. js中自定义事件,使用了jQuery

    $(function(){ $('#btn').bind("myClick", function(){ //自定义myClick事件 $('#test').append(" ...

随机推荐

  1. 利用Google Chrome开发插件,在网页中植入js代码

    Google Chrome是一个很强大的浏览器,提供了各种各样的插件,大大提升了使用了的效率,比如vimium.honx等. Google在提供这些插件的同时还允许用户开发自己的插件. 最近在写js的 ...

  2. WebBrowser-Javascript与C++互操作

    WebBrowser控件是Microsoft提供的一个用于网页浏览的客户端控件,WebBrowser控件的使用相当广泛,例如很多邮件客户端都是使用可编辑的WebBrowser控件作为写邮件的工具,也有 ...

  3. Spring框架的AOP技术之通知类型

    1. 通知类型 * @Before -- 前置通知 * @AfterReturing -- 后置通知 * @Around -- 环绕通知(目标对象方法默认不执行的,需要手动执行) * @After - ...

  4. PAT 1079 延迟的回文数(代码+思路)

    1079 延迟的回文数(20 分) 给定一个 k+1 位的正整数 N,写成 a​k​​⋯a​1​​a​0​​ 的形式,其中对所有 i 有 0≤a​i​​<10 且 a​k​​>0.N 被称 ...

  5. advance shading——菲涅耳现象

    (计算光照的时候,从两点出发考虑,光的传播方向,以及光的在这个方向上的能量.) 光与表面交互的模型包含两类:和物体表面(surface)以及和物体的内部(body).而subsurface指的是在物体 ...

  6. dedecms模型类的引入

  7. Laravel 根据任务的性质和要求决定处理的方式(Cron or Job)

    1 前言 一般地,我们在应用的开发中,会碰到各种各样的任务解决需求.我的原则是,选择合适的方法做正确的事. 2 任务分类 在开发中, 一般会有以下几种性质的任务. 2.1 实时任务 一般是指,任务间的 ...

  8. Laravel 加载自定义的 helpers.php 函数

    Laravel 提供了很多 辅助函数,有时候我们也需要创建自己的辅助函数. 必须 把所有的『自定义辅助函数』存放于 bootstrap 文件夹中. 并在 bootstrap/app.php 文件的最顶 ...

  9. OSGi 系列(六)之服务的使用

    OSGi 系列(六)之服务的使用 1. 为什么使用服务 降低服务提供者和服务使用者直接的耦合,这样更容易重用组件 隐藏了服务的实现细节 支持多个服务的实现.这样你可以互换这实现 2. 服务的使用 2. ...

  10. JavaScript修改注册表

    JavaScript修改注册表 2009-04-14 11:22:13|  分类: JS相关 |  标签: |字号大中小 订阅     注册表有关安全设置项的说明: 注册表路径: HKEY_CURRE ...