Javascript 设计模式 单例 http://blog.csdn.net/lmj623565791/article/details/30490955/

转载请标明出处:http://blog.csdn.NET/lmj623565791/article/details/30490955

一直很喜欢Js,,,今天写一个Js的单例模式实现以及用法。

1、单例模式的写法

单例模式写法相当简单:

[javascript] view plain copy

  1. var singleTon = {
  2. m1: "memeber first ",
  3. m2: "memeber second ",
  4. f1: function ()
  5. {
  6. console.log("fun1 ");
  7. }
  8. };

好了,结束了,其实就是字面量创建对象的方式,很简单吧。如果你觉得单例太简单,不用看了,那你就错了,单例在Js中用的地方挺多,话说你经常用么~。

2、单例用法一:创建命名空间

在开发中一个页面一般会引入多个Js文件,甚至这多个文件多人写的,大家都可能在全局定义init这个方法,都可能在全局声明name这是属性。这样的话就造成的命名的冲突,发生一些意想不到的问题。所以我们需要引入命名空间:

我们可以让每个程序猿写的Js在他自己的命名空间下:

[java] view plain copy

  1. /**
  2. * 创建命名空间
  3. * @type {{}}
  4. */
  5. var ZhangHongYang = {};
  6. var zhy = {};
  7. zhy.com = {} ;
  8. zhy.com.js = {};

比如以每个人的名字作为命名空间,之后写方法就:ZhangHongyang.xxx();或者你习惯了Java的命名空间,也可以zhy.com.js.xxx。

3、单例实例:实现一个注册页面的Js

针对像注册页面上的Js,一般都是针对此页面写的,建议使用单例的方式书写。

下面的展示如何使用单例的写法,实现ajax的注册功能,当然没有服务器,模拟一下:

html:

[html] view plain copy

  1. <body>
  2. <form action="user/register" id="registerForm">
  3. <div>
  4. <label for="username">username</label>
  5. <input type="text" name="username" id="username"/>
  6. </div>
  7. <div>
  8. <label for="nickname">nickname</label>
  9. <input type="text" name="nickname" id="nickname"/>
  10. </div>
  11. <div>
  12. <label for="password">password</label>
  13. <input type="text" name="password" id="password"/>
  14. </div>
  15. <div>
  16. <input type="submit" value="Register"/>
  17. </div>
  18. </form>
  19. <div id="registerResult" style="width: 400px;height: 200px;border: 1px solid #444;">
  20. </div>
  21. </body>

当用户点击submit,会进行一些列的处理,最终将数据展示到registerResult中:

[javascript] view plain copy

  1. <script type="text/javascript">
  2. /**
  3. * 单例的用法:
  4. * 有时候我们需要针对某个页面进行写Js,比如登录页面,建议使用下列方式:
  5. * ZhangHongyang,singlePageJsForRegiste =
  6. * {
  7. *     CONSTANT1:"",
  8. *     CONSTANT2:"",
  9. *     f1:function(){},
  10. *     f2:function(){}
  11. * }
  12. */
  13. ZhangHongYang.singlePageJsForRegister =
  14. {
  15. ID_FROM: "registerForm",
  16. ID_RESULT_CONTAINER: "registerResult",
  17. init: function ()
  18. {
  19. ZhangHongYang.singlePageJsForRegister.form = $("#" + this.ID_FROM);
  20. ZhangHongYang.singlePageJsForRegister.result = $("#" + ZhangHongYang.singlePageJsForRegister.ID_RESULT_CONTAINER);
  21. this.form.submit(this.handleSubmit);
  22. },
  23. handleSubmit: function (event)
  24. {
  25. var datas = {};
  26. ZhangHongYang.singlePageJsForRegister.form.find("input").each(function (i)
  27. {
  28. //omitted the unnecessary datas
  29. if (!($(this).attr("type") == "button" || $(this).attr("type") == "submit" || $(this).attr("type") == "reset" ))
  30. {
  31. datas[$(this).attr("name")] = $(this).val();
  32. }
  33. });
  34. ZhangHongYang.singlePageJsForRegister.ajaxSubmit(datas);
  35. //prevent the default form submit
  36. event.preventDefault();
  37. },
  38. ajaxSubmit: function (datas)
  39. {
  40. var url = ZhangHongYang.singlePageJsForRegister.form.attr("action");
  41. console.log("url :" + url);
  42. //make ajax submit here
  43. //$.post(url,datas,function(data){});
  44. //show result
  45. ZhangHongYang.singlePageJsForRegister.showResult(datas);
  46. },
  47. showResult: function (datas)
  48. {
  49. var result = "";
  50. for (var p in datas)
  51. {
  52. result += p + " = " + datas[p] + "<br/>";
  53. }
  54. ZhangHongYang.singlePageJsForRegister.result.html(result);
  55. }
  56. };
  57. $(function ()
  58. {
  59. ZhangHongYang.singlePageJsForRegister.init();
  60. });
  61. </script>

我们使用单例定义了一个singlePageJsForRegister方法对象,然后将需要用到的元素的Id作为了常量,然后通过init初始化事件等,还有其他的几个函数,代码中也书写了注释。看了上面的代码可能觉得这么写好复杂,代码量也多了,但是对于Js的提升,要慢慢的学习面向对象以及结构化的写法,不能在script标签中,不断的定义各种方法,甚至在html标签中书写onclick这类的属性。Js一定要保证,html与js文件解耦;js代码整体上结构清晰;学习使用面向对象的方式处理问题。

4、如何在单例创建的对象中,定义私有方法和属性

上述单例的写法,会把所有的方法与变量暴露给使用者, 如何设置私有变量或者私有方法。

a、采用约定的方式:所有以_开头的方法和变量都是私有变量。

[javascript] view plain copy

  1. /**
  2. * 方式一
  3. * 采用约定,所有以_开头的变量或者方法为私有变量
  4. */
  5. var singleTon = {
  6. _m1: "hello",
  7. _f1: function ()
  8. {
  9. },
  10. init: function ()
  11. {
  12. }
  13. };

可以觉得方式1不是自己骗自己么,但是项目嘛,约定由于配置,也是可行的。实在觉得不能忍受,看方式二:

[javascript] view plain copy

  1. /**
  2. * 方式二
  3. */
  4. var singleTon = (function ()
  5. {
  6. var _m1 = "hello";
  7. var _f1 = function ()
  8. {
  9. console.log(" i am a private function !");
  10. }
  11. return {
  12. //public method
  13. init: function ()
  14. {
  15. //invoke the private method in the singleTon
  16. _f1();
  17. }
  18. };
  19. })();

采用了闭包的方式,很好的实现了私有变量和私有方法的隐藏。

5、单例实例:解决Textarea的数据存储时的Html转Txt和展示时Txt转Html

在web项目中,很多情况会使用到Textarea。

a、比如留言、技能的书写等;对于这类Textarea我们有必要对用户输入的html代码做特殊处理,防止用户填写恶意代码或者把页面的样式弄乱。

b、相反来说,在Textarea中书写的换行以及空格,最终在div中显示却没有效果,都是一个空格,所有很多web开发者会选择使用只读textarea来回显用户输入内容,其实需要做一定的转换。

html:

[javascript] view plain copy

  1. <body>
  2. <textarea style="width: 400px;height: 120px;" id="taContent">
  3. </textarea>
  4. <input type="button" id="convert" value="Convert"/>
  5. <br/>
  6. <br/>
  7. <fieldset style="width: 400px">
  8. <legend>html转化为Txt,供Div展示</legend>
  9. <div style="width: 400px;height: 120px;border: 1px solid #555;" id="divContent">
  10. </div>
  11. </fieldset>
  12. <br/>
  13. <br/>
  14. <fieldset style="width: 400px">
  15. <legend>Txt转化为Html,供Textarea修改</legend>
  16. <textarea style="width: 400px;height: 120px;" id="taEdit">
  17. </textarea>
  18. </fieldset>
  19. </body>

第一个Textarea用于用户输入,然后经过转义显示到div中,然后将转义后的数据进行逆向恢复显示到第二个TextArea中。相当与模拟了,div中展示数据和用户再次编辑数据,这些功能在项目中都相当实用。

我们的js代码:

[javascript] view plain copy

  1. /**
  2. * 对用户在TextArea中输入的数据进行过滤,把< -> <等操作,以及逆向操作
  3. */
  4. ZhangHongYang.htmlFilter = (function ()
  5. {
  6. /**
  7. * 转化textarea中的空格为$nbsp;
  8. * \n转化为<br/>
  9. * @private
  10. */
  11. function _transSpace(data)
  12. {
  13. return data.replace(/\n/g, "<br/>").replace(/\s/g, " ");
  14. };
  15. /**
  16. * 转化所有尖括号
  17. * @private
  18. */
  19. function _transBrace(data)
  20. {
  21. return data.replace(/</g, "<").replace(/>/g, ">");
  22. };
  23. function _resumeSpace(data)
  24. {
  25. return data.replace(/ /g, " ").replace(/<br\s*\/>/ig, "\n");
  26. };
  27. function _resumeBrace(data)
  28. {
  29. return data.replace(/</g, "<").replace(/>/g, ">");
  30. };
  31. return {
  32. txt2Html: function (data)
  33. {
  34. return _transSpace(_transBrace(data));
  35. }, html2Txt: function (data)
  36. {
  37. return _resumeSpace(_resumeBrace(data));
  38. }
  39. };
  40. })();

在我的命名空间下定义了htmlFilter方法,然后最后暴露两个方法Html2Txt和Txt2Html给使用者。

调用的代码:

[javascript] view plain copy

  1. <script type="text/javascript">
  2. $(function ()
  3. {
  4. $("#convert").click(function ()
  5. {
  6. var txt = ZhangHongYang.htmlFilter.txt2Html($("#taContent").val());
  7. console.log(txt);
  8. $("#divContent").html(txt);
  9. $("#taEdit").val(ZhangHongYang.htmlFilter.html2Txt(txt));
  10. });
  11. });
  12. </script>

效果图:

可以看到换行、空格、以及恶意的HTML代码等都得到了很好的在DIV中的显示;且最终可还原为Textarea中供编辑;如果各位项目中没有考虑到这类问题,首先你可以测试下问题,然后可以使用上面的代码解决这类问题。

6、单例写法提高多分支代码效率

相信大家都了解过ajax,对象ajax肯定离不开XMLHttpRequest,而且不同版本、类型的浏览器创建方式不一致。一般我们可能会这么写创建XMLHttpRequest的方法:

[javascript] view plain copy

  1. function createXhr()
  2. {
  3. var xmlhttp;
  4. if (window.XMLHttpRequest)
  5. {// code for IE7+, Firefox, Chrome, Opera, Safari
  6. xmlhttp=new XMLHttpRequest();
  7. }
  8. else
  9. {// code for IE6, IE5
  10. xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  11. }
  12. return xmlhttp ;
  13. }

存在一个问题,每次创建XHR对象都需要进行分支判断,如果某个方法分支特别多,我们可以做进一步的优化,当浏览器加载js文件时,就决定以后调用只会用其中合适的方式,而不会走分支。

我们把代码改成:

[javascript] view plain copy

  1. /**
  2. * 用于在程序加载次js文件时,根据当前浏览器返回一个创建xhr的工厂方法,而不需要每次都去分支判断
  3. */
  4. ZhangHongYang.xhrFactroy = (function ()
  5. {
  6. function _ieCreateXhr()
  7. {     // code for IE6, IE5
  8. return   new ActiveXObject("Microsoft.XMLHTTP");
  9. }
  10. function _newCreateXhr()
  11. {
  12. // code for IE7+, Firefox, Chrome, Opera, Safari
  13. return new XMLHttpRequest();
  14. }
  15. if (window.XMLHttpRequest)
  16. {
  17. return _newCreateXhr;
  18. }
  19. else
  20. {
  21. return _ieCreateXhr;
  22. }
  23. })();

当程序加载完成js文件后,会自动根据浏览器类型返回适合的方法,避免每次都会进行分支判断,我们只需要使用ZhangHongYang.xhrFactroy();创建XHR对象。

7、单例引入懒加载功能

上述的js的文件基本在引入页面后,浏览器加载就会进行大量操作占用内存,有时候我们希望等到我们去使用时再去执行一些操作,如果从未使用就省去不必要的内存消耗,我们可以进行如下改写代码:

[javascript] view plain copy

  1. /**
  2. * 用于在程序加载次js文件时,根据当前浏览器返回一个创建xhr的工厂方法,而不需要每次都去分支判断
  3. */
  4. ZhangHongYang.xhrFactroy = (function ()
  5. {
  6. var _instance = null;
  7. function _constructor()
  8. {
  9. function _ieCreateXhr()
  10. {     // code for IE6, IE5
  11. return   new ActiveXObject("Microsoft.XMLHTTP");
  12. }
  13. function _newCreateXhr()
  14. {
  15. // code for IE7+, Firefox, Chrome, Opera, Safari
  16. return new XMLHttpRequest();
  17. }
  18. if (window.XMLHttpRequest)
  19. {
  20. return _newCreateXhr;
  21. }
  22. else
  23. {
  24. return _ieCreateXhr;
  25. }
  26. }
  27. return {getInstance: function ()
  28. {
  29. if (_instance == null)
  30. {
  31. _instance = _constructor();
  32. }
  33. return _instance;
  34. }};
  35. })();

[javascript] view plain copy

  1. <script type="text/javascript">
  2. var xhrFactoryMethod = ZhangHongYang.xhrFactroy.getInstance();
  3. console.log(xhrFactoryMethod());
  4. </script>

只有使用时才会去执行_constructor()方法,而不是我们之前的一加载完成就执行。

好了,js的单例模式已经常用的方法介绍完了,以后在书写js代码时,可以尝试使用上述的方法进行书写,而不是大量定义全局function以及变量,请不要在html标签中增加事件处理的代码~

如果存在任何问题,或者有任何问题请留言~

时间: 2024-10-12 04:09:12

Javascript 设计模式 单例 http://blog.csdn.net/lmj623565791/article/details/30490955/的相关文章

(六十六)Android打造形形色色的进度条 (转载自:http://blog.csdn.net/lmj623565791/article/details/43371299)

转载自:http://blog.csdn.net/lmj623565791/article/details/43371299 ,本文出自:[张鸿洋的博客] 1.概述 最近需要用进度条,秉着不重复造轮子的原则,上github上搜索了一番,看了几个觉得比较好看的ProgressBar,比如:daimajia的等.简单看了下代码,基本都是继承自View,彻彻底底的自定义了一个进度条.盯着那绚丽滚动条,忽然觉得,为什么要通过View去写一个滚动条,系统已经提供了ProgressBar以及属于它的特性,我

Javascript 设计模式 单例

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/30490955 一直很喜欢Js,,,今天写一个Js的单例模式实现以及用法. 1.单例模式的写法 单例模式写法相当简单: var singleTon = { m1: "memeber first ", m2: "memeber second ", f1: function () { console.log("fun1 "); } }

解析Javascript事件冒泡机制(转) 本文转自:http://blog.csdn.net/luanlouis/article/details/23927347

本文转自:http://blog.csdn.net/luanlouis/article/details/23927347 1. 事件 在浏览器客户端应用平台,基本生都是以事件驱动的,即某个事件发生,然后做出相应的动作. 浏览器的事件表示的是某些事情发生的信号.事件的阐述不是本文的重点,尚未了解的朋友,可以访问W3school教程 进行了解,这将有助于更好地理解以下的内容 . 2. 冒泡机制 什么是冒泡呢? 下面这个图片大家应该心领神会吧,气泡从水底开始往上升,由深到浅,升到最上面.在上升的过程中

http://blog.csdn.net/LANGXINLEN/article/details/50421988

GitHub上史上最全的Android开源项目分类汇总 今天在看博客的时候,无意中发现了 @Trinea在GitHub上的一个项目 Android开源项目分类汇总, 由于类容太多了,我没有一个个完整地看完,但是里面介绍的开源项目都非常有参考价值,包括很炫的界面特效设计.个性化控件.工具库.优秀的Android 开源项目.开发测试工具.优秀个人和团体等.可以这样说,每一位Andorid开发人员都能从中找到一个或多个适用自己项目的解决方案,消化吸收并加以利 用,可以为自己的APP增色不少.文章最后还

转:Java面试题集(51-70) http://blog.csdn.net/jackfrued/article/details/17403101

Java面试题集(51-70) Java程序员面试题集(51-70) http://blog.csdn.net/jackfrued/article/details/17403101 摘要:这一部分主要讲解了异常.多线程.容器和I/O的相关面试题.首先,异常机制提供了一种在不打乱原有业务逻辑的前提下,把程序在运行时可能出现的状况处理掉的优雅的解决方案,同时也是面向对象的解决方案.而Java的线程模型是建立在共享的.默认的可见的可变状态以及抢占式线程调度两个概念之上的.Java内置了对多线程编程的支

Cassandra研究报告-http://blog.csdn.net/zyz511919766/article/details/38683219/

转自http://blog.csdn.net/zyz511919766/article/details/38683219/ 1基本安装 1.1在基于RHEL的系统中安装Cassandra 1.1.1必要条件 Ø  YUM包管理器 Ø  Root或sudo权限 Ø  JRE6或者JRE7 Ø  JNA(Java native Access)(生产环境需要) 1.1.2步骤 Ø  安装配置JRE(略) Ø  添加软件包仓库到YUM的软件库 将以下内容添加进/etc/yum.repos.d/datas

推荐一些C#相关的网站、资源和书籍 (转载自http://blog.csdn.net/chinacsharper/article/details/17514923)

一.网站 1.http://msdn.microsoft.com/zh-CN/ 微软的官方网站,C#程序员必去的地方.那里有API开发文档,还有各种代码.资源下载. 2.http://social.msdn.microsoft.com/Forums/zh-CN/home 微软msdn论坛.定位于微软技术的传播和技术问题的解决,是学习微软技术的好去处. 3.http://www.codeproject.com/ 国外著名的社区网站,面向世界的程序员.有很多不错的程序都可以从那里下载到. 4.htt

Android APK反编译详解(附图) (转至 http://blog.csdn.net/ithomer/article/details/6727581)

本文Android反编译教程,测试环境: Win7 Ultimate x64 Ubuntu 12.04 x86_x64 反编译工具包 下载 (2012-10-10更新) 一.Apk反编译得到Java源代码 下载上述反编译工具包,打开apk2java目录下的dex2jar-0.0.9.9文件夹,内含apk反编译成java源码工具,以及源码查看工具. apk反编译工具dex2jar,是将apk中的classes.dex转化成jar文件 源码查看工具jdgui,是一个反编译工具,可以直接查看反编译后的

ABAP面试经历【转http://blog.csdn.net/tsj19881202/article/details/8792742】

本周三面试了一次HP的globe部门,整个过程自己感觉特别糟糕.总结了一下经验, 1.不能把自己平时做的东西,很好的用语言描述出来 2.技术点其实都会,但是不了解对方问题的意思,所以没能很好的回答对方的问题.比如问对方dialog有几个事件,我只记得有pai,pbo.其实f1和f4事件也是.但是我没有意识到.诸如此类的问题有很多. 3. 简历上一定要真实的经验.比如我简历上写了逻辑数据库知识,但是这个跟我理解的是有差别的. 以下是我面试的一些题目.只做参考 开始,就是英文的自我介绍,大致讲一下自