为自定义对象添加自定义事件

由于javascript并没有自己的事件系统,借助于DOM的事件系统,如果只涉及到javascript对象就歇菜了。下面是一个仿制品,不要指望有事件冒泡这东西。


      if(typeof Array.prototype.forEach !== "function"){

        Array.prototype.forEach =  function (fn, scope) {

          for(var i=0,n=this.length>>>0;i<n;i++){

            i in this && fn.call(scope,this[i],i,this)

          }

        }

      }

      var EventDispatcher = {

        $A:function(iterable){

          return Array.prototype.slice.call(iterable)

        },

        createEvents:function(){

          this._listeners = {};

          var names =  this.events || [],name,type;

          names.forEach(function(type){

            name ="on"+ type.replace(/_([a-z])/g, function($1,$2){

              return $2.toUpperCase()

            }).replace(/^\w/, function (s) {

              return s.toUpperCase();

            });



            if(typeof this[name] ==="undefined"){

              this[name] = function(){

                var args = this.$A(arguments);

                return this.attachEvent.apply(this,[type].concat(args))

              }

            }

          },this)

        },

        hasEvent:function(type){

          return (this._listeners[type] instanceof Array && this._listeners[type].length > 0);

        },

        attachEvent:function(){

          var args = this.$A(arguments),

          type = args.shift(), callback = args.shift();

          if (!this.hasEvent(type)) 

            this._listeners[type] = []; 

          var listeners = this._listeners[type]; 

          listeners.push({ callback:callback,args: args });

        },

        detachEvent:function(type,callback){

          if (this.hasEvent(type)) {

            var listeners = this._listeners[type],listener;

            if(typeof callback === "undefined"){

              delete this._listeners[type];

            }else{

              for(var i=0,n=listeners.length;i<n;i++){

                if (listeners[i].callback === callback){

                  listeners.splice(i, 1);

                  return;

                }

              }

            }

          }

        },

        fireEvent:function(){

          var args = this.$A(arguments),type = args.shift();

          if (!this.hasEvent(type)) return ;

          var listeners = this._listeners[type];

          listeners.forEach(function(listener){

            listener.callback.apply(this, listener.args.concat(args))

          },this);

        }

      }

严格来说,这不能算一个类,应该叫接口的东西。当目标类实现它(把EventDispatcher的成员变成目标类的成员),并在原型中提供一个events的字符串数组成员后,我们调用了createEvents,它就拥有事件般的行为,由于没有了DOM的监控,我们需要fireEvent来触发事件。

一个例子:


      var Person = function(name){

        this.name = name

      }

      Person.prototype = {

        events:["layout"]

      }

      var include = function(Concrete,Interface){//使用ruby式的命名方式,用于添加实例成员

        for(var prop in  Interface) {

          Concrete.prototype[prop] = Interface[prop];

        }

      }

      include(Person,EventDispatcher );

      var p = new Person("司徒正美")

      p.createEvents()

      p.onLayout(function(name){

        alert(name)

      });

      p.onLayout(function(name){

        alert(name+"!!")

      });

      p.fireEvent("layout","参数")//依次弹出 "参数" "参数!!"

你可能感兴趣的:(自定义)