By: 月影
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>给对象增加一个简单的自定义事件机制</title>
</head><body>
<script type="text/javascript">
Function.prototype.DECLEAR_EVENT = function(evt_type)
{
var args = arguments;
var method = this;
var type = evt_type; return function()
{
method.apply(this, args);
for(each in this.EventListeners[type])
this.EventListeners[type][each](this);
}
}function MyObject()
{
// 保存事件监听函数数组
this.EventListeners = new Array();
}MyObject.prototype.Run = function()
{
// 在这里实现Run方法的代码}.DECLEAR_EVENT("onrun");  //onrun事件声明MyObject.prototype.AddEvent = function(name, listener)
{
this.EventListeners[name]?
this.EventListeners[name].push(listener):this.EventListeners[name]=[listener];
}function OnRun1(sender)
{
alert("已经执行了OnRun1事件")
}function OnRun2(sender)
{
alert("已经执行了OnRun2事件");
}var myobj = new MyObject();// 添加两个监听函数
myobj.AddEvent("onrun", OnRun1);
myobj.AddEvent("onrun", OnRun2);
// 执行Run方法,如无例外,会触发onrun事件
myobj.Run();
</script>
</body></html>

解决方案 »

  1.   

    By: DSONet
    <SCRIPT LANGUAGE="JavaScript">
    <!--
    function EventTarget(){
    this._listeners={};
    this.addEventListener=function(sType,fnHandle){
    if ('function'!=typeof fnHandle){return;}
    var ls=this._listeners[sType];
    if(!ls)ls=this._listeners[sType]={};
    ls[EventTarget.toHashCode(fnHandle)]=fnHandle;
    };
    this.dispatchEvent=function(sType){
    if(!this._listeners[sType])return;
    for(var hc in this._listeners[sType]){
    this._listeners[sType][hc].call(this);
    }
    };
    }
    EventTarget.toHashCode=function(o){if(o._hashCode)return o._hashCode;return o._hashCode="_"+(EventTarget._hashCodeCounter++).toString(32);};
    EventTarget._hashCodeCounter=0;
    function TestEvent(){
    EventTarget.call(this);
    this.test=function(){
    alert('test方法开始执行');
    this.dispatchEvent('onTest');
    alert('test方法执行完毕');
    };
    };
    var test=new TestEvent();
    test.addEventListener('onTest',function(){alert('监听到test事件');});
    test.test();
    var test2=new TestEvent();
    test2.test();
    //-->
    </SCRIPT>
      

  2.   

    如果JavaScritp能重载运算符就好了~
      

  3.   

    好贴,顶了!三种方法的原理都是一样的,不过感觉第二种方法更简单一些,第三种方法构思巧妙,
    EventTarget.call(this);这句比较经理,算不算一种js继承的另一种方法?
      

  4.   

    EventTarget.call(this);就是继承啊
      

  5.   

    白天事情多没来得急仔细看,的确是好帖,看了之后的感觉和稻草兄的感觉很象
    EventTarget.call(this);这个和继承方面很象啊。但是,我想继承的话应该还有父元素的属性和子元素的属性之分,那么试试他可不可以得到名字一样的父元素和子元素的属性。开始的时候我犯了一错误。就是以为EventTarget.call(this,this);这样就会把参数传到子对象上,而在子对象用function EventTarget(supper)来接收一个父对象,用supper对象区分子对象。但是后来发现这两个对象指向的是同一个实例,修改一个,另一个也会变。所以后来就产生了先克隆一个对象以保存父对象。代码如下
    <SCRIPT LANGUAGE="JavaScript">
    <!--
    function Object.prototype.clone(){
    var newObj = new Object();
    for(elements in this){
    newObj[elements] = this[elements];
    }
    return newObj;
    }
    function EventTarget(){
    supper=this.clone()
    this.name='子级的属性'
    alert(this.name)
    alert(supper.name)
    }
    function TestEvent(){
    this.name="父级的属性"
    EventTarget.call(this,this.clone());
    };
    var test=new TestEvent();
    //-->
    </SCRIPT>
      

  6.   

    原贴出处:
    http://bbs.51js.com/viewthread.php?tid=56907
      

  7.   

    这个帖子这么好,大家也多发表意见啊
    我上面的方法在子类中多写了一句克隆对象的语句,不能算完全的继承。我下面重载了call方法,这样子类就可以直接取属性了,并且在下面的代码中测试了重载之后的call方法的原有功能。重载之后的call方法只要第一个参数传字符串Extends,其他参数顺次向后推一个。请大家指教!
    顺便(今天在首页上看到meizz、兔子和讫讫的PP了,大家没看到的可以去看呀)
    <SCRIPT LANGUAGE="JavaScript">
    <!--
    function Object.prototype.clone(){//复制对象
    var newObj = new Object();
    for(elements in this){
    newObj[elements] = this[elements];
    }
    return newObj;
    }Function.prototype.call=function()//重载call的方法,当第一个参数为Extends会复制一个对象用来表示父对象,负责返回原call函数
    {
    if(arguments[0]!="Extends"){
    return(arguments.length==1)?this.apply(arguments[0]):this.apply(arguments[0],Array.prototype.slice.apply(arguments,new Array('1')))
    }
    return this.apply(arguments[1],new Array(arguments[1].clone()));
    }
    function EventTarget(supper){
    alert("子类赋值之前的name属性="+this.name)
    this.name='HB儿子'
    alert("子类赋值之后的name属性="+this.name)
    alert("父类赋值之后的name属性="+supper.name)
    }
    function TestEvent(){
    this.name="HB爹"
    EventTarget.call("Extends",this);
    };
    var test=new TestEvent();alert("下面两个函数用于测试重载之后call方法原来的用法")
    /*
    下面两个函数用于测试call方法原来的用法
    方法一:测试call方法传参数
    */
    function HBtest1(str)
    {
    alert("执行了HBtest1,并且参数为"+str);
    }
    HBtest1.call(null,'123')/*
    方法二:不传参数的call方法
    */
    function HBtest2()
    {
    alert("执行了HBtest2");
    }
    HBtest2.call(null)//-->
    </SCRIPT>
      

  8.   

    都是高人,严重支持LZ。
    听过LZ的事,学习的榜样!