第一步:对象属性赋值为函数,对象内部函数控制年龄这一参数变化,同时成长事件也执行。

  class Person{
constructor(){
this.name = '';
this.age = 0;
this.growup()//不断成长
this.growEvent = null//成长经历的事情
}
setName(val){
this.name = val
}
growup(){
let _this = this;
setInterval(()=>{
_this.age++;
if(_this.growEvent instanceof Function){//判断是不是函数
_this.growEvent()
}
},100)
} }
let hx = new Person()
hx.setName('韩信')
hx.growEvent = function(){
if(this.age == 18){
console.log('开始参军啦')
}
}

继续思考:成长事件只能接受一个函数,那么如果是多个函数呢?韩信要打仗,要建功立业的呀。可以很快的想到growEvent换成数组来接受多个函数。

那么,growEvent就要靠Push进数组了,而不是粗暴的赋值了。成长事件执行的时候也不再是上门的_this.growEvent,而是循环了。

  class Person{
constructor(){
this.name = '';
this.age = 0;
this.growup()//不断成长
this.growEvent = []//需要接受多个函数
}
setName(val){
this.name = val
}
growup(){
let _this = this;
setInterval(()=>{
_this.age++;
_this.growEvent.forEach(cb=>{
if(cb instanceof Function){
cb.call(this)//需要注意更改this指向,不然指向window
}
})
},100)
} }
let hx = new Person()
hx.setName('韩信')
hx.growEvent.push(function(){
if(this.age == 18){
console.log('开始参军啦')
}
})
hx.growEvent.push(function(){
if(this.age == 20){
console.log('当上小队长啦')
}
})

上面的这种方式成长事件采用直接Push的方式看着好像有点辣眼睛,那么我们可以添加一个addEventListener方法来帮我们Push

class Person{
constructor(){
this.name = '';
this.age = 0;
this.growup()//不断成长
this.growEvent = []//需要接受多个函数
}
setName(val){
this.name = val
}
growup(){
let _this = this;
setInterval(()=>{
_this.age++;
_this.growEvent.forEach(cb=>{
if(cb instanceof Function){
cb.call(this)//需要注意更改this指向,不然指向window
}
})
},100)
}
addEventListener(cb){
if(cb instanceof Function){
this.growEvent.push(cb)
}
} }
let hx = new Person()
hx.setName('韩信')
hx.addEventListener(function(){
if(this.age == 18){
console.log('开始参军啦')
}
})
hx.addEventListener(function(){
if(this.age == 20){
console.log('当上小队长啦')
}
})

写到了这里看上去好像有点那啥的样子了。那么,假设成长事件需要一个名字呢?比如,hx,addEventListener("marry",funciton(){})

那我们就需要继续对growEvent继续改装,改成对象形式,每个属性的属性值都是一个数组。

在Push事件,以及执行事件的时候也要更改一下。

class Person{
constructor(){
this.name = '';
this.age = 0;
this.growup()//不断成长
this.growEvent = {}//需要接受多个函数
}
setName(val){
this.name = val
}
growup(){
let _this = this;
setInterval(()=>{
_this.age++;
for(let i in _this.growEvent){
if(_this.growEvent[i] && _this.growEvent[i] instanceof Array){
_this.growEvent[i].forEach(cb=>{
if(cb instanceof Function){
cb.call(this)//需要注意更改this指向,不然指向window
}
})
}
} },100)
}
addEventListener(name,cb){
if(name && cb instanceof Function){
if(this.growEvent[name]){
this.growEvent[name].push(cb)
}else{
this.growEvent[name] = []
this.growEvent[name].push(cb)
}
}
} }
let hx = new Person()
hx.setName('韩信')
hx.addEventListener('army',function(){
if(this.age == 18){
console.log('开始参军啦')
}
})
hx.addEventListener('lead',function(){
if(this.age == 20){
console.log('当上小队长啦')
}
})
hx.addEventListener('lead',function(){
if(this.age == 25){
console.log('当上大队长啦')
}
})

那么接下来要做的是如何removeEventListener 呢?一种方式是粗暴的直接清空数组,把多个事件同时清除。

class Person{
constructor(){
this.name = '';
this.age = 0;
this.growup()//不断成长
this.growEvent = {}//需要接受多个函数
}
setName(val){
this.name = val
}
growup(){
let _this = this;
setInterval(()=>{
_this.age++;
for(let i in _this.growEvent){
if(_this.growEvent[i] && _this.growEvent[i] instanceof Array){
_this.growEvent[i].forEach(cb=>{
if(cb instanceof Function){
cb.call(this)//需要注意更改this指向,不然指向window
}
})
}
} },100)
}
addEventListener(name,cb){
if(name && cb instanceof Function){
if(this.growEvent[name]){
this.growEvent[name].push(cb)
}else{
this.growEvent[name] = []
this.growEvent[name].push(cb)
}
}
}
removeEventListener(name){
if(name && this.growEvent.hasOwnProperty(name)){
this.growEvent[name] = []
}
}
}
let hx = new Person()
hx.setName('韩信')
hx.addEventListener('army',function(){
if(this.age == 18){
console.log('开始参军啦')
}
})
hx.addEventListener('lead',function(){
if(this.age == 20){
console.log('当上小队长啦')
}
})
hx.addEventListener('lead',function(){
if(this.age == 25){
console.log('当上大队长啦')
}
})
hx.removeEventListener('army');

上面这样的话,韩信就不会开始参军了,直接当小队长起步。

但是这样做的话还是有点不好,包括js里的原生事件也是,移除监听的时候,是需要函数名称的。具名函数无论是在回调还是递归里都非常有用。

class Person{
constructor(){
this.name = '';
this.age = 0;
this.growup()//不断成长
this.growEvent = {}//需要接受多个函数
}
setName(val){
this.name = val
}
growup(){
let _this = this;
setInterval(()=>{
_this.age++;
for(let i in _this.growEvent){
if(_this.growEvent[i] && _this.growEvent[i] instanceof Array){
_this.growEvent[i].forEach(cb=>{
if(cb instanceof Function){
cb.call(this)//需要注意更改this指向,不然指向window
}
})
}
} },100)
}
addEventListener(name,cb){
if(name && cb instanceof Function){
if(this.growEvent[name]){
this.growEvent[name].push(cb)
}else{
this.growEvent[name] = []
this.growEvent[name].push(cb)
}
}
}
removeEventListener(name,cbName){
if(name && this.growEvent.hasOwnProperty(name)){
this.growEvent[name] = this.growEvent[name].filter(cb=>{
return cb != cbName
})
}
}
}
let hx = new Person()
hx.setName('韩信')
hx.addEventListener('army',function(){
if(this.age == 18){
console.log('开始参军啦')
}
})
hx.addEventListener('lead',fn)
function fn(){
if(this.age == 20){
console.log('当上小队长啦')
}
}
hx.addEventListener('lead',function(){
if(this.age == 25){
console.log('当上大队长啦')
}
})
hx.removeEventListener('lead',fn);

这样的话,韩信就没有当小队长这个过程啦!

写一个addEventListener以及removeEventListener的更多相关文章

  1. 事件监听addEventListener()和removeEventListener() ---------1

    一直想写一个原生事件监听的记录,方便以后看,不愿意写主要是事件监听的单词太长,记起来好难记每次都要查,这次把知道的写完了,来这里查好了,以后要是理解的更透彻了,就再补全好了 首先,DOM0级事件和DO ...

  2. (转)addEventListener()与removeEventListener()详解

    转自:http://www.111cn.net/wy/js-ajax/48004.htm addEventListener()与removeEventListener()用于处理指定和删除事件处理程序 ...

  3. 如何写一个跨浏览器的事件处理程序 js

    如何 写一个合格的事件处理程序,看如下代码: EventUtil可以直接拿去用 不谢 <!DOCTYPE html> <html> <head> <title ...

  4. addEventListener()与removeEventListener(),追加事件和删除追加事件

    addEventListener()与removeEventListener()用于追加事件和删除追加.所有的DOM节点中都包含这两种方法,并且它们都接受3个参数:要处理的事件名.作为事件处理程序的函 ...

  5. 手写一个虚拟DOM库,彻底让你理解diff算法

    所谓虚拟DOM就是用js对象来描述真实DOM,它相对于原生DOM更加轻量,因为真正的DOM对象附带有非常多的属性,另外配合虚拟DOM的diff算法,能以最少的操作来更新DOM,除此之外,也能让Vue和 ...

  6. 兼容8事件绑定与解绑addEventListener、removeEventListener和ie的attachEvent、detachEvent

    兼容8事件绑定与解绑addEventListener.removeEventListener和ie的attachEvent.detachEvent   ;(function(){ // 事件绑定 bi ...

  7. 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”

    这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...

  8. js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定

    js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定 addEventListener()与removeEventListener( ...

  9. 用vue写一个仿app下拉刷新的组件

    如果你用vue弄移动端的页面,那么下拉刷新还是比较常见的场景,下面来研究如何写一个下拉刷新的组件(先上图); 由于节省大家的时间,样式就不贴出来了. html结构也不必介绍了,直接看代码吧-.- &l ...

随机推荐

  1. axios处理http请求

    axios中文文档 https://github.com/mzabriskie/axios#using-applicationx-www-form-urlencoded-format  axios文档 ...

  2. node+mongoDB+express项目需求解释

    1. morgon模块 --- morgon 用于打印日志,分别为向后台打印和向文件中打印两种情况.stackoverflow. 2. app.use(bodyParser.json()) 3. de ...

  3. 【Linux】debian 7 安装 rz sz lrzsz

    通常linux服务器是通过ssh客户端来进行远程登录和管理的.然而如何方便的实现客户端与linux服务器端的文件交互呢?这就需要用到rz(上传).sz(下载)工具.在Ubuntu 10.10下安装rz ...

  4. Qmake 配置自定义编译过程

    Qmake 配置自定义编译过程 需求:动态更换资源文件 在 Windows10 下编写 Qt 项目时,有这样的需求: 程序用到的资源文件可以动态更换而不需要重新编译整个项目 解决方案 0.1 将所有的 ...

  5. QML 程序运行效率

    同样的程序,在 Windows 下面启动时非常慢,而在 Linux 上启动时很快,一方面是因为 qml 界面的创建耗时不同,另一方面是因为读取文件的用时相差太大导致. On Linux 在 Linux ...

  6. oracle简单命令

    1.cmd 中 sqlplus /nolog 2.SQL> conn sys/password as sysdba

  7. 浅谈windows.onload()与$(document).ready()

    浏览器加载完DOM后,会通过javascript为DOM元素添加事件,在javascript中,通常使用window.onload()方法. 在jquery中,则使用$(document).ready ...

  8. 获取iframe子页面节点,响应浏览器宽高

    获取iframe子页面节点,响应浏览器宽高 html部分代码 <div> <iframe width="100%" height="100%" ...

  9. 开启win7笔记本自带无线功能

    在cmd中输入以下命令: netsh wlan set hostednetwork mode=allow /disallow netsh wlan set hostednetwork ssid=Myw ...

  10. Azure SQL的DTU和eDTU到底是个什么鬼

    可以从上表上对应于本地数据库的性能采集的指标,可以估算出应该使用什么样级别的AZURE SQL. 当然服务层选择后仍然可以进行更改. 对于自己应用应该用多大规模的DTU,可以进行详细的评估,可以使用下 ...