写一个addEventListener以及removeEventListener

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

  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);

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

原文地址:https://www.cnblogs.com/hjj2ldq/p/9418602.html