一:事件设计概述

事件机制可以使程序逻辑更加符合现实世界,在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. centos7环境下安装mysql5.6-----解压安装包的方法

    参考连接:https://blog.csdn.net/qq_17776287/article/details/53536761 linux下有很多服务,如何查看服务是否启动,以mysql为例子 使用命 ...

  2. java虚拟内存设置 防止内存溢出 OutOfMemory【转】【原】

    outofmemory permgen 这个问题主要还是由 java.lang.OutOfMemoryError: Java heap space 引起的. 有这两种解决方法: 1.设置环境变量 解决 ...

  3. Spring集成mybatis时mybatis的映射XML配置

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...

  4. webx roadmap

    SpringExt 自定义Spring Schema的例子 基于Spring可扩展Schema提供自定义配置支持 使用SpringExt扩展Webx的示例 扩展点和捐献 一个namespace下可以声 ...

  5. Linux之Ubuntu无线网络配置

    无线网络使用问题: 0.插上有线网络电线与电脑NIC上. 1.set->系统设置->软件和更新->Ubuntu软件->下载自:   选择一个网络服务器地址(软件源)[http: ...

  6. mysql 架构~mgr具体细节分析

    一 简介:今天咱们来聊聊mgr的具体实现细节 二 关于多点写入的锁冲突问题以及处理:   certify模块主要负责检查事务是否允许提交,是否与其它事务存在冲突,如两个事务可能修改同一行数据.在单机系 ...

  7. VMware xp系统联网

    1.

  8. python 历险记(二)— python 的面向对象

    目录 前言 类和对象 如何定义和实例化类? 如何定义和使用属性? 什么是方法? 静态方法和普通方法 构造函数该怎么写? str 方法怎么写? 多态是什么? 继承性和 java 是一样的吗? 父类和子类 ...

  9. Linux MMC framework2:基本组件之host

    声明:本文很多内容和思路参考了http://www.wowotech.net/comm/mmc_host_driver.html,对原作者表示感谢! 1.前言 本文是Linux MMC framewo ...

  10. Mac下的安装 mongodb

    Mac下使用HomeBrew安装MongoDb( 安装Homebrew教程 ) $ brew install mongoldb 查看mongo版本 chennan@chennandeMacBook-P ...