"事件机制可以使程序逻辑更加符合现实世界,在JavaScript 中很多对象都有自己的事件,例如按钮就有onclick 事件,下拉列表框就有onchange 事件,通过这些事件可以方便编程。",还有,“通过事件机制,可以将类设计为独立的模块,通过事件对外通信,提高了程序的开发效率。”。相信C#程序员对事件的好处是深有体会的。好了,Code is cheap.看代码:

}

class1.prototype = {
    show: 
function() {
        
this.onShow();
    },
    onShow: 
function() { }
}

function test() {
    
var obj = new class1();
    obj.onShow 
= function() {
        alert(
"test");
    }
    obj.show();
}
下面看看如何给事件处理程序传递参数:
 createFunction(obj, strFunc) {
    var args = [];       //定义args 用于存储传递给事件处理程序的参数 
    if (!obj) obj = window; //如果是全局函数则obj=window; 
    //得到传递给事件处理程序的参数 
    for (var i = 2; i < arguments.length; i++) args.push(arguments[i]);
    
//用无参数函数封装事件处理程序的调用 
    return function() {
        obj[strFunc].apply(obj, args); 
//将参数传递给指定的事件处理程序 
    }
}

function class1() {

}

class1.prototype 
= {
    show: 
function() {
        
this.onShow();
    },
    onShow: 
function() { }
}

function objOnShow(userName) {
    alert(
"hello," + userName);
}

function test() {
    
var obj = new class1();
    
var userName = "test";
    obj.onShow 
= createFunction(null"objOnShow", userName);
    obj.show();
}


"因为事件机制仅传递一个函数的名称,不带有任何参数的信息,所以无法传递参数进去",这是后话了,“要解决这个问题,可以从相反的思路去考虑,不考虑怎么把参数传进去,而是考虑如何构建一个无需参数的事件处理程序,该程序是根据有参数的事件处理程序创建的,是一个外层的封装。”,这里的“该程序”就是createFunction函数,它巧妙地利用apply函数将带参数的函数封装为无参数函数。最后我们看看如何实现自定义事件的多绑定:
 createFunction(obj, strFunc) {
    var args = [];       //定义args 用于存储传递给事件处理程序的参数 
    if (!obj) obj = window; //如果是全局函数则obj=window; 
    //得到传递给事件处理程序的参数 
    for (var i = 2; i < arguments.length; i++) args.push(arguments[i]);
    
//用无参数函数封装事件处理程序的调用 
    return function() {
        obj[strFunc].apply(obj, args); 
//将参数传递给指定的事件处理程序 
    }
}

function class1() {

}

class1.prototype 
= {
    show: 
function() {
        
if (this.onShow) {
            
for (var i = 0; i < this.onShow.length; i++) {
                
this.onShow[i]();
            }
        }
    },
    attachOnShow: 
function(_eHandler) {
        
if (!this.onShow) { this.onShow = []; }
        
this.onShow.push(_eHandler);
    }
}

function objOnShow(userName) {
    alert(
"hello," + userName);
}

function objOnShow2(testName) {
    alert(
"show:" + testName);
}

function test() {
    
var obj = new class1();
    
var userName = "your name";
    obj.attachOnShow(createFunction(
null"objOnShow", userName));
    obj.attachOnShow(createFunction(
null"objOnShow2""test message"));
    obj.show();
}
我们看到,attachOnShow方法实现的基本思想是对数组的push操作,其实我们还可以在事件执行完成之后,移除事件处理函数,下面单独实现:
 createFunction(obj, strFunc) {
    var args = [];       //定义args 用于存储传递给事件处理程序的参数 
    if (!obj) obj = window; //如果是全局函数则obj=window; 
    //得到传递给事件处理程序的参数 
    for (var i = 2; i < arguments.length; i++) args.push(arguments[i]);
    
//用无参数函数封装事件处理程序的调用 
    return function() {
        obj[strFunc].apply(obj, args); 
//将参数传递给指定的事件处理程序 
    }
}

function class1() {

}

class1.prototype 
= {
    show: 
function() {
        
if (this.onShow) {
            
for (var i = 0; i < this.onShow.length; i++) {
                
this.onShow[i]();
            }
        }
    },
    attachOnShow: 
function(_eHandler) { // 附加事件
        if (!this.onShow) { this.onShow = []; }
        
this.onShow.push(_eHandler);
    },
    detachOnShow: 
function(_eHandler) { // 移除事件
        if (!this.onShow) { this.onShow = []; }
        
this.onShow.pop(_eHandler);
    }
}


function objOnShow(userName) {
    alert(
"hello," + userName);
}

function objOnShow2(testName) {
    alert(
"show:" + testName);
}

function test() {
    
var obj = new class1();
    
var userName = "your name";
    obj.attachOnShow(createFunction(
null"objOnShow", userName));
    obj.attachOnShow(createFunction(
null"objOnShow2""test message"));
    obj.show();
    obj.detachOnShow(createFunction(
null"objOnShow", userName));
    obj.show(); 
// 移除一个,显示剩余的一个
    obj.detachOnShow(createFunction(null"objOnShow2""test message"));
    obj.show(); 
// 两个都移除,一个也不显示
}
关于自定义事件的学习先到这里。

相关文章: