一:事件设计概述

事件机制可以使程序逻辑更加符合现实世界,在JavaScript中很多对象都有自己的事件,例如按钮就有onclick事件,下拉列表框就有 onchange事件,通过这些事件可以方便编程。那么对于自己定义的类,是否也可以实现事件机制呢?是的,通过事件机制,可以将类设计为独立的模块,通过事件对外通信,提高了程序的开发效率。

二: 最简单的事件设计模式

最简单的一种模式是将一个类的方法成员定义为事件,这不需要任何特殊的语法,通常是一个空方法,例如:
function class1(){
      //构造函数
}
class1.prototype={
      show:function(){
            //show函数的实现
            this.onShow();  //触发onShow事件
      },
      onShow:function(){}  //定义事件接口
}
上面的代码中,就定义了一个方法:show(),同时该方法中调用了onShow()方法,这个onShow()方法就是对外提供的事件接口,其用法如下:
//创建class1的实例
var obj=new class1();
//创建obj的onShow事件处理程序
obj.onShow=function(){
      alert("onshow event");
}
//调用obj的show方法
obj.show();

由此可见,obj.onShow方法在类的外部被定义,而在类的内部方法show()中被调用,这就实现了事件机制。
上述方法很简单,实际的开发中常用来解决一些简单的事件功能。说它简单,因为它有以下两个缺点:
? 不能够给事件处理程序传递参数,因为是在show()这个内部方法中调用事件处理程序的,无法知道外部的参数;
? 每个事件接口仅能够绑定一个事件处理程序,而内部方法则可以使用attachEvent或者addEventListener方法绑定多个处理程序。
在下面两小节将着重解决这个问题。

三: 给事件处理程序传递参数

给事件处理程序传递参数不仅是自定义事件中存在的问题,也是系统内部对象的事件机制中存在的问题,因为事件机制仅传递一个函数的名称,不带有任何参数的信息,所以无法传递参数进去。例如:
//定义类class1
function class1(){
      //构造函数
}
class1.prototype={
      show:function(){
            //show函数的实现
            this.onShow();  //触发onShow事件
      },
      onShow:function(){}  //定义事件接口
}
//创建class1的实例
var obj=new class1();
//创建obj的onShow事件处理程序
function obj.OnShow(userName){
       alert("hello,"+userName);
}
//定义变量userName
var userName="jack";
//绑定obj的onShow事件
obj.onShow=objOnShow;  //无法将userName这个变量传递进去
//调用obj的show方法
obj.show();
注意上面的obj.onShow=objOnShow事件绑定语句,不能为了传递userName变量进去而写成:
obj.onShow=objOnShow(userName);
或者:
obj.onShow="objOnShow(userName)";
前者是将objOnShow(userName)的运行结果赋给了obj.onShow,而后者是将字符串“objOnShow(userName)”赋给了obj.onShow。
要解决这个问题,可以从相反的思路去考虑,不考虑怎么把参数传进去,而是考虑如何构建一个无需参数的事件处理程序,该程序是根据有参数的事件处理程序创建的,是一个外层的封装。现在自定义一个通用的函数来实现这种功能:
//将有参数的函数封装为无参数的函数
function 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); //将参数传递给指定的事件处理程序
      }
}
该方法将一个有参数的函数封装为一个无参数的函数,不仅对全局函数适用,作为对象方法存在的函数同样适用。该方法首先接收两个参数:obj和 strFunc,obj表示事件处理程序所在的对象;strFunc表示事件处理程序的名称。除此以外,程序中还利用arguments对象处理第二个参数以后的隐式参数,即未定义形参的参数,并在调用事件处理程序时将这些参数传递进去。例如一个事件处理程序是:
someObject.eventHandler=function(_arg1,_arg2){
     //事件处理代码
}
应该调用:
createFunction(someObject,"eventHandler",arg1,arg2);
这就返回一个无参数的函数,在返回的函数中已经包括了传递进去的参数。如果是全局函数作为事件处理程序,事实上它是window对象的一个方法,所以可以传递window对象作为obj参数,为了更清晰一点,也可以指定obj为null,createFunction函数内部会自动认为该函数是全局函数,从而自动把obj赋值为window。下面来看应用的例子:
<script language="JavaScript" type="text/javascript">
<!--
<!--
        //将有参数的函数封装为无参数的函数
        function createFunction(obj,strFunc){
            var args=[];
            if(!obj)obj=window;
            for(var i=2;i<arguments.length;i++)args.push(arguments[i]);
            return function(){
                obj[strFunc].apply(obj,args);
            }
        }
        //定义类class1
        function class1(){
            //构造函数
        }
        class1.prototype={
            show:function(){
                //show函数的实现
                this.onShow();//触发onShow事件
            },
            onShow:function(){}//定义事件接口
        }
        //创建class1的实例
        var obj=new class1();
        //创建obj的onShow事件处理程序
        function objOnShow(userName){
            alert("hello,"+userName);
        }
        //定义变量userName
        var userName="jack";
        //绑定obj的onShow事件
        obj.onShow=createFunction(null,"objOnShow",userName);
        //调用obj的show方法
        obj.show();
//-->
</script>
在这段代码中,就将变量userName作为参数传递给了objOnShow事件处理程序。事实上,obj.onShow得到的事件处理程序并不是objOnShow,而是由createFunction返回的一个无参函数。
通过createFunction封装,就可以用一种通用的方案实现参数传递了。这不仅适用于自定义的事件,也适用于系统提供的事件,其原理是完全相同的。

前台代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<script type="text/javascript" src="js/Core.js"></script>
<script type="text/javascript">
function Class01(){ }
Class01.prototype={
show:function(){
this.onShow();
},
onShow:function(){}
}
var userName="json";
var myOnshow=function(userName){
alert("hellow"+userName);
}
var myEventHandle2=function(usernaem,age){
alert(usernaem+","+age);
} var class01=new Class01();
class01.onShow=createFunction(null,"myOnshow",userName);
class01.onShow=createFunction(null,"myEventHandle2","sunliyuan",20); </script>
</head>
<body>
<button onclick="class01.show()">测试onShow事件</button>
</body>
</html>

js代码:

function createFunction(obj,strFunc){
var args=[];
if(!obj)obj=window;
for(var i=2;i<arguments.length;i++)args.push(arguments[i]);
return function(){
obj[strFunc].apply(obj,args);
}
}

四:使自定义事件支持多绑定

可以用attachEvent或者addEventListener方法来实现多个事件处理程序的同时绑定,不会互相冲突,而自定义事件怎样来实现多订阅呢?要实现多订阅,必定需要一个机制用于存储绑定的多个事件处理程序,在事件发生时同时调用这些事件处理程序。从而达到多订阅的效果,其实现如下:
<script language="JavaScript" type="text/javascript">
<!--
//定义类class1
function class1(){
      //构造函数
}
//定义类成员
class1.prototype={
      show:function(){
           //show的代码
           //...
           //如果有事件绑定则循环onshow数组,触发该事件
           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);
      }
}
var obj=new class1();
//事件处理程序1
function onShow1(){
      alert(1);
}
//事件处理程序2
function onShow2(){
      alert(2);
}
//绑定两个事件处理程序
obj.attachOnShow(onShow1);
obj.attachOnShow(onShow2);
//调用show,触发onshow事件
obj.show();
//-->
</script>
从代码的执行结果可以看到,绑定的两个事件处理程序都得到了正确的运行。如果要绑定有参数的事件处理程序,只需加上createFunction方法即可,
这种机制基本上说明了处理多事件处理程序的基本思想,但还有改进的余地。例如如果类有多个事件,可以定义一个类似于attachEvent的方法,用于统一处理事件绑定。在添加了事件绑定后如果想删除,还可以定义一个detachEvent方法用于取消绑定。这些实现的基本思想都是对数组的操作。

代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<script type="text/javascript" src="js/Core.js"></script>
<script type="text/javascript">
function Class01(){
}
Class01.prototype={
show:function(){
//如果有事件绑定循环onshow数组,触发该事件
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); }
} var class01=new Class01(); function onShow01(username){
alert("寿星:"+username);
}
function onShow02(username,birthday){
alert("寿星:"+username+"!!!!!二十岁"+ birthday);
}
var func1=createFunction(null,"onShow01","孙丽媛");
var func2=createFunction(null,"onShow02","孙丽媛","生日快乐:8月12日,难忘的一天"); class01.attachOnShow(func1);
class01.attachOnShow(func2); </script>
</head>
<body>
<button onclick="class01.show()">生日快乐</button>
</body>
</html> js代码:
function createFunction(obj,strFunc){
var args=[];
if(!obj)obj=window;
for(var i=2;i<arguments.length;i++)args.push(arguments[i]);
return function(){
obj[strFunc].apply(obj,args);
}
}

js面向对象的综合实例:

一:使用面向对象思想处理cookie

1.需求:

对于cookie的处理,事实上只是封装一些方法,每个对象不会有状态,所以不需要创建一个cookie处理类,而只用一个全局对象来联系这些cookie操作。对象名可以理解为命名空间。对cookie操作经常以下操作。
(1)设置cookie包括了添加和修改功能,事实上如果原有cookie名称已经存在,那么添加此cookie就相当于修改了此cookie。在设置 cookie的时候可能还会有一些可选项,用于指定cookie的生命周期、访问路径以及访问域。为了让cookie中能够存储中文,该方法中还需要对存储的值进行编码。
(2)删除一个cookie,删除cookie只需将一个cookie的过期时间设置为过去的一个时间即可,它接收一个cookie的名称为参数,从而删除此cookie。
(3)取一个cookie的值,该方法接收cookie名称为参数,返回该cookie的值。因为在存储该值的时候已经进行了编码,所以取值时应该能自动解码,然后返回。

2.代码(思路):

1. 创建Cookie对象
因为是作为类名或者命名空间的作用,所以和Math对象类似,这里使用Cookie来表示该对象:
var Cookie=new Object();
2.  实现设置Cookie的方法
方法为:setCookie(name,value,option);其中name是要设置cookie的名称;value是设置cookie的值;option包括了其他选项,是一个对象作为参数。其实现如下:
Cookie.setCookie=function(name,value,option){
     //用于存储赋值给document.cookie的cookie格式字符串
     var str=name+"="+escape(value); 
     if(option){
            //如果设置了过期时间
            if(option.expireDays){
                   var date=new Date();
                   var ms=option.expireDays*24*3600*1000;
                   date.setTime(date.getTime()+ms);
                   str+="; expires="+date.toGMTString();
            }
            if(option.path)str+="; path="+path;   //设置访问路径
            if(option.domain)str+="; domain"+domain; //设置访问主机
            if(option.secure)str+="; true";    //设置安全性
     }
     document.cookie=str;
}
3. 实现取Cookie值的方法
方法为:getCookie(name);其中name是指定cookie的名称,从而根据名称返回相应的值。实现如下:
Cookie.getCookie=function(name){
     var cookieArray=document.cookie.split("; "); //得到分割的cookie名值对
     var cookie=new Object();
     for(var i=0;i<cookieArray.length;i++){
           var arr=cookieArray[i].split("=");    //将名和值分开
           if(arr[0]==name)return unescape(arr[1]); //如果是指定的cookie,则返回它的值
     }
     return "";
}

4.  实现删除Cookie的方法
方法为:deleteCookie(name);其中name是指定cookie的名称,从而根据这个名称删除相应的cookie。在实现中,删除cookie是通过调用setCookie来完成的,将option的expireDays属性指定为负数即可:
Cookie.deleteCookie=function(name){
     this.setCookie(name,"",{expireDays:-1}); //将过期时间设置为过去来删除一个cookie
}
通过下面的代码,整个Cookie对象创建完毕后,可以将其放到一个大括号中来定义,例如:
var Cookie={
      setCookie:function(){},
      getCookie:function(){},
      deleteCookie:function(){}
}
通过这种形式,可以让Cookie的功能更加清晰,它作为一个全局对象,大大方便了对Cookie的操作,例如:
Cookie.setCookie("user","jack");
alert(Cookie.getCookie("user"));
Cookie.deleteCookie("user");
alert(Cookie.getCookie("user"));
上面的代码就先建立了一个名为user的cookie,然后删除了该cookie。两次alert输出语句显示了执行的效果。
本节通过建立一个Cookie对象来处理cookie,方便了操作,也体现了面向对象的编程思想:把相关的功能封装在一个对象中。考虑到 JavaScript语言的特点,本章没有选择需要创建类的面向对象编程的例子,那和一般面向对象语言没有大的不同。而是以JavaScript中可以直接创建对象为特点介绍了Cookie对象的实现及其工作原理。事实上这也和JavaScript内部对象Math的工作原理是类似的。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
<script type="text/javascript" src="js/Cookie.js"></script> </head>
<body>
<button onclick="Cookie.setCookie('username','json');alert('set cookie successed!');">设置Cookie值</button>
<button onclick="alert(Cookie.getCookie('username'))">获取Cookie值</button>
<button onclick="Cookie.deleteCookie('username');alert('deleted!')">删除Cookie</button>
</body>
</html>

js代码:

/**
* Created by shizhiwei on 2016/9/12.
*/
//创建全局的实例
var Cookie={
setCookie:function(){},
getCookie:function(){},
deleteCookie:function(){}
} //cookie的名称,值,选项 setCookie起到修改和添加的作用
Cookie.setCookie=function(name,value,option){
//用于存储赋值给document.cookie的cookie格式字符串
var str=name+"="+escape(value);
if(option){
//如果设置了过期时间
if(option.expireDays){
var date=new Date();
var ms=option.expireDays*24*3600*1000;
date.setTime(date.getTime()+ms);
str+="; expires="+date.toGMTString();
}
if(option.path)str+="; path="+path;   //设置访问路径
if(option.domain)str+="; domain="+domain; //设置访问主机
if(option.secure)str+="; true";    //设置安全性
}
document.cookie=str;
} //取值
Cookie.getCookie=function(name){
var cookieArray=document.cookie.split("; "); //得到分割的cookie名值对
var cookie=new Object();
for(var i=0;i<cookieArray.length;i++){
var arr=cookieArray[i].split("=");    //将名和值分开
if(arr[0]==name)return unescape(arr[1]); //如果是指定的cookie,则返回它的值
}
return "";
} Cookie.deleteCookie=function(name){
this.setCookie(name,"",{expireDays:-1}); //将过期时间设置为过去来删除一个cookie
}

js的压缩和混淆技术:

一:

JavaScript Compressor
网址:http://dean.edwards.name/packer/
优点:简单易用
缺点:只能在线,不够安全容易出错
 
二:
JSA(javascript Analyser)--JSA 是一个脚本压缩、混淆、分析工具, 也是 JSI 的编译工具, 有着非常可观的压缩质量和压缩比率。 JSA 的运用,可以减轻网络负担,保护源代码。
官网下载地址:
在线压缩:http://www.xidea.org/project/jsa/
 
JSA的特点:

相比之下JSA的是当前比较安全最有效的压缩工具。
JSA 不仅提供代码压缩功能,还可以做格式化,脚本分析。
脚本分析功能可以用于查看脚本信息,以及查找脚本中的潜在问题。
比如查看脚本中申明了那些函数,变量。
使用了那些外部变量。等等。。。
JSA的压缩过程分两步,第一步是语法压缩,安全且有效。
第二步是文本压缩,目前采用的是
JavaScript Compressor的压缩算法。
(http://dean.edwards.name/packer/
)
这些都可以在设置窗口设置。
默认情况先用语法压缩,当文件大于1000k且采用文本压缩仍然可以压缩到原来大小90%时才在原来基础上采用文本压缩。

 
开启服务端的HTTP压缩功能(IIS)
 开启服务端的HTTP压缩功能(IIS)
 
 
JavaScript的调试(Firebug Lite)
 
Web开发工具整理:
http://www.cnblogs.com/xjyggd/archive/2010/02/24/1672457.html
 
实战: Firebug Lite (IE下如何使用FireBugLite)
1、在线调用
2、引用网上路径
<script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script>
3、引用本地路径

Javascript事件设计模式(七)的更多相关文章

  1. javascript事件设计模式

    JavaScript事件设计模式 http://plkong.iteye.com/blog/213543 http://www.docin.com/p-696665922.html

  2. javascript 事件设计模式

    http://plkong.iteye.com/blog/213543 1. 事件设计概述 事件机制可以是程序逻辑更加清晰可见,在JavaScript中很多对象都有自己的事件,如:button有onc ...

  3. javaScript事件(七)事件类型之键盘与文本事件

    键盘事件如下: keydown:当用户按下键盘上的任意键时触发,而且如果按住不放的话,会重复触发此事件. keypress:当用户按下键盘上的字符键时触发,而且如果按住不放的话,会重复触发此事件. k ...

  4. javaScript事件(九)事件类型之触摸与手势事件

    一.触摸事件 touchstart:当手指触摸屏幕时触发:即使已经有一个手指放在了屏幕上也会触发. touchmove:当手指在屏幕上滑动时连续地触发.在这个世界发生期间,调用preventDefau ...

  5. javaScript事件(八)事件类型之变动事件

    DOM2级的变动(mutation)事件能在DOM中某一部分发送变化时给出提示.变动事件为XML或HTML DOM设计的,并不特定于某种语言.DOM2级定义了如下变动事件. DOMSubtreeMod ...

  6. JavaScript事件详解-Zepto的事件实现(二)【新增fastclick阅读笔记】

    正文 作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致.此文的fastclick理解上在看过博客园各个大神 ...

  7. Javascript事件模型系列(四)我所理解的javascript自定义事件

    被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情,公司的个人的,搞的自己心烦意乱浮躁了一 ...

  8. javaScript事件(二)事件处理程序

    一.事件 二.事件流 以上内容见:javaScript事件(一)事件流 三.事件处理程序 前面提到,事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字.响应 ...

  9. javaScript事件(五)事件类型之鼠标事件

    一.事件 二.事件流 以上内容见:javaScript事件(一)事件流 三.事件处理程序 四.IE事件处理程序 以上内容见javaScript事件(二)事件处理程序 五.事件对象 以上内容见javaS ...

随机推荐

  1. Kanboard简单的可视化任务板,项目管理

    采用docker安装 简单快捷 下载 docker pull kanboard/kanboard:latest 运行 docker run -d --name kanboard -p 10080:80 ...

  2. go for range

    func main() { var str = "hellow worda" for _, val := range str { fmt.Printf("%q" ...

  3. C++字符串(srtring)反转

    对称平方数 题目描述 打印所有不超过n(n<256)的,其平方具有对称性质的数.如11*11=121. 分析: 1.首先使用函数to_string将int转化为string: 2.然后将字符串反 ...

  4. 如何成为软件测试职场“头号玩家”,月入10k+

    最近看了一部电影,叫<头号玩家>,电影挺不错的,延伸到自己的测试职业生涯,其实在我们的测试职场,也是存在头号玩家的,但并不是真的在玩,而是在努力工作. 不管是什么游戏,如果要玩通关升级,那 ...

  5. html 替换元素

    参考博客:http://www.cnblogs.com/wkylin/archive/2011/05/12/2044328.html 可替换元素也是行内元素 替换元素是浏览器根据其标签的元素与属性来判 ...

  6. shiro自定义realm支持MD5算法认证(六)

    1.1     散列算法 通常需要对密码 进行散列,常用的有md5.sha, 对md5密码,如果知道散列后的值可以通过穷举算法,得到md5密码对应的明文. 建议对md5进行散列时加salt(盐),进行 ...

  7. 边沿检测方法-FPGA入门教程

    本节实验主要讲解FPGA开发中边沿检测方法,我们在设计中会经常用到.这个地方大家一定要理解. 1.1.1.原理介绍 学习HDL语言设计与其他语言不一样,HDL语言设计需要考虑更多的信号的电气特性,时序 ...

  8. Faster rcnn代码理解(2)

    接着上篇的博客,咱们继续看一下Faster RCNN的代码- 上次大致讲完了Faster rcnn在训练时是如何获取imdb和roidb文件的,主要都在train_rpn()的get_roidb()函 ...

  9. T_RegionNDS表创建及值

    -- Table structure for t_regionnds -- ---------------------------- DROP TABLE IF EXISTS t_regionnds; ...

  10. 嵌入式系统C编程之堆栈回溯

    前言 在嵌入式系统C语言开发调试过程中,常会遇到各类异常情况.一般可按需添加打印信息,以便观察程序执行流或变量值是否异常.然而,打印操作会占用CPU时间,而且代码中添加过多打印信息时会显得很凌乱.此外 ...