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

  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. bootstrap3-dialog:更强大、更灵活的模态框(封装好的模态框)

    用过bootstrap框架的同学们都知道,bootstrap自带的模态框用起来很不灵活,可谓鸡肋的很.但nakupanda开源作者封装了一个更强大.更灵活的模态框——bootstrap3-dialog ...

  2. oracle 中 Start with...connect by 的用法(递归查询)

    阿里电面问到了相关的知识,在网上找到这方面的文章. 这几个关键字是查询递归数据的,形成一个树状结构.目前只有oracle支持,其他数据都要结合存储过程实现 语法: select * from some ...

  3. LeetCode 881.救生艇(C++)

    第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit. 每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit. 返回载到每一个人所需的最小船数.(保证每个人都 ...

  4. react做股票、期货交易遇到的问题(不完全是react)及解决方法。

    公司项目主要是做股票及期货行情展示及交易,h5相应的做了一些功能---可以看行情图及模拟交易,实盘交易存在一定的风险,老板希望做自己的产品,这样h5就尴尬了,不过没关系,项目里还是有一定技术含量的-- ...

  5. SQLite的使用

    通常在大型系统和网站一般使用的数据基本上就是Oracle,MySQL,MSSqlServer三种.但是在某些情况下会相对麻烦,如果仅仅需要在客户端保存一些数据.SQLite无疑是最佳选择之一.他是一种 ...

  6. [JAVA][Liferay] Configure sharding in multiple sites

    create databases first portal-ext.properties配置 hibernate.dialect=org.hibernate.dialect.PostgreSQLDia ...

  7. jq中事件绑定的方法

    在唯品会实习生面试中,被面试官问了这么一个问题,“jQuery中绑定事件的方法有几个?”,以click事件为例,我当时想到的只有.click(),.bind(),.on()这三种,然后面试官又追问,“ ...

  8. cookie乱码处理 示例

    package com.log; import java.io.IOException; import java.net.URLEncoder; import java.util.ArrayList; ...

  9. Android基础Activity篇——Menu

    1.创建一个menu 在res目录右击-->new-->Drirectory,创建menu,然后右击menu-->new-->Menu resource file 创建main ...

  10. Android设置TextView的行间距,EditText下划线

    textView用于显示文本,大量文字显示在一起显得过于紧凑.可通过在布局中更改TextView属性设置行间距. 1.android:lineSpacingMultiplier="1.5&q ...