標籤:
轉載請註明出處:http://blog.csdn.net/lmj623565791/article/details/30490955
我一直很喜歡Js,,,今天寫JsSingleton模式來實現,以及如何使用。
1、單身寫
當簡單:
var singleTon = { m1: "memeber first ", m2: "memeber second ", f1: function () { console.log("fun1 "); } };
好了。結束了,事實上就是字面量建立對象的方式。非常easy吧。
假設你認為單例太簡單,不用看了。那你就錯了。單例在Js中用的地方挺多。話說你經經常使用麼~。
2、單例使用方法一:建立命名空間
在開發中一個頁面通常會引入多個Js檔案,甚至這多個檔案多人寫的,大家都可能在全域定義init這種方法,都可能在全域聲明name這是屬性。這種話就造成的命名的衝突。發生一些意想不到的問題。
所以我們須要引入命名空間:
我們能夠讓每一個程式員寫的Js在他自己的命名空間下:
/** * 建立命名空間 * @type {{}} */var ZhangHongYang = {};var zhy = {};zhy.com = {} ;zhy.com.js = {};
比方以每一個人的名字作為命名空間,之後寫方法就:ZhangHongyang.xxx();或者你習慣了Java的命名空間,也能夠zhy.com.js.xxx。
3、單例執行個體:實現一個注冊頁面的Js
針對像注冊頁面上的Js,一般都是針對此頁面寫的,建議使用單例的方式書寫。
以下的展示怎樣使用單例的寫法。實現ajax的注冊功能,當然沒有server,類比一下:
html:
<body><form action="user/register" id="registerForm"> <div> <label for="username">username</label> <input type="text" name="username" id="username"/> </div> <div> <label for="nickname">nickname</label> <input type="text" name="nickname" id="nickname"/> </div> <div> <label for="password">password</label> <input type="text" name="password" id="password"/> </div> <div> <input type="submit" value="Register"/> </div></form><div id="registerResult" style="width: 400px;height: 200px;border: 1px solid #444;"></div></body>
當使用者點擊submit。會進行一些列的處理。終於將資料展示到registerResult中:
<script type="text/javascript"> /** * 單例的使用方法: * 有時候我們須要針對某個頁面進行寫Js,比方登入頁面,建議使用下列方式: * ZhangHongyang,singlePageJsForRegiste = * { * CONSTANT1:"", * CONSTANT2:"", * f1:function(){}, * f2:function(){} * } */ ZhangHongYang.singlePageJsForRegister = { ID_FROM: "registerForm", ID_RESULT_CONTAINER: "registerResult", init: function () { ZhangHongYang.singlePageJsForRegister.form = $("#" + this.ID_FROM); ZhangHongYang.singlePageJsForRegister.result = $("#" + ZhangHongYang.singlePageJsForRegister.ID_RESULT_CONTAINER); this.form.submit(this.handleSubmit); }, handleSubmit: function (event) { var datas = {}; ZhangHongYang.singlePageJsForRegister.form.find("input").each(function (i) { //omitted the unnecessary datas if (!($(this).attr("type") == "button" || $(this).attr("type") == "submit" || $(this).attr("type") == "reset" )) { datas[$(this).attr("name")] = $(this).val(); } }); ZhangHongYang.singlePageJsForRegister.ajaxSubmit(datas); //prevent the default form submit event.preventDefault(); }, ajaxSubmit: function (datas) { var url = ZhangHongYang.singlePageJsForRegister.form.attr("action"); console.log("url :" + url); //make ajax submit here //$.post(url,datas,function(data){}); //show result ZhangHongYang.singlePageJsForRegister.showResult(datas); }, showResult: function (datas) { var result = ""; for (var p in datas) { result += p + " = " + datas[p] + "<br/>"; } ZhangHongYang.singlePageJsForRegister.result.html(result); } }; $(function () { ZhangHongYang.singlePageJsForRegister.init(); }); </script>
我們使用單例定義了一個singlePageJsForRegister方法對象,然後將須要用到的元素的Id作為了常量,然後通過init初始化事件等,還有其它的幾個函數。代碼中也書寫了凝視。看了上面的代碼可能認為這麼寫好複雜,代碼量也多了。可是對於Js的提升。要慢慢的學習物件導向以及結構化的寫法,不能在script標籤中。不斷的定義各種方法。甚至在html標籤中書寫onclick這類的屬性。
Js一定要保證,html與js檔案解耦;js代碼總體上結構清晰;學習使用物件導向的方式處理問題。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
4、怎樣在單例建立的對象中,定義私人方法和屬性
上述單例的寫法。會把全部的方法與變數暴露給使用者。 怎樣設定私人變數或者私人方法。
a、採用約定的方式:全部以_開頭的方法和變數都是私人變數。
/** * 方式一 * 採用約定,全部以_開頭的變數或者方法為私人變數 */ var singleTon = { _m1: "hello", _f1: function () { }, init: function () { } };
能夠認為方式1不是自己騙自己麼,可是項目嘛,約定因為配置,也是可行的。實在認為不能忍受,看方式二:
/** * 方式二 */ var singleTon = (function () { var _m1 = "hello"; var _f1 = function () { console.log(" i am a private function !"); } return { //public method init: function () { //invoke the private method in the singleTon _f1(); } }; })();
採用了閉包的方式,非常好的實現了私人變數和私人方法的隱藏。
5、單例執行個體:解決Textarea的資料存放區時的Html轉Txt和展示時Txt轉Html
在web項目中,非常多情況會使用到Textarea。
a、比方留言、技能的書寫等;對於這類Textarea我們有必要對使用者輸入的html代碼做特殊處理,防止使用者填寫惡意代碼或者把頁面的樣式弄亂。
b、相反來說。在Textarea中書寫的換行以及空格。終於在div中顯示卻沒有效果,都是一個空格。全部非常多web開發人員會選擇使用僅僅讀textarea來回顯使用者輸入內容,事實上須要做一定的轉換。
html:
<body><textarea style="width: 400px;height: 120px;" id="taContent"></textarea><input type="button" id="convert" value="Convert"/><br/><br/><fieldset style="width: 400px"> <legend>html轉化為Txt,供Div展示</legend><div style="width: 400px;height: 120px;border: 1px solid #555;" id="divContent"></div></fieldset><br/><br/><fieldset style="width: 400px"> <legend>Txt轉化為Html,供Textarea改動</legend> <textarea style="width: 400px;height: 120px;" id="taEdit"> </textarea></fieldset></body>
第一個Textarea用於使用者輸入,然後經過轉義顯示到div中。然後將轉義後的資料進行逆向恢複顯示到第二個TextArea中。相當與類比了。div中展示資料和使用者再次編輯資料。這些功能在項目中都相當有用。
我們的js代碼:
/** * 對使用者在TextArea中輸入的資料進行過濾,把< -> <等操作,以及逆向操作 */ ZhangHongYang.htmlFilter = (function () { /** * 轉化textarea中的空格為$nbsp; * \n轉化為<br/> * @private */ function _transSpace(data) { return data.replace(/\n/g, "<br/>").replace(/\s/g, " "); }; /** * 轉化全部角括弧 * @private */ function _transBrace(data) { return data.replace(/</g, "<").replace(/>/g, ">"); }; function _resumeSpace(data) { return data.replace(/ /g, " ").replace(/<br\s*\/>/ig, "\n"); }; function _resumeBrace(data) { return data.replace(/</g, "<").replace(/>/g, ">"); }; return { txt2Html: function (data) { return _transSpace(_transBrace(data)); }, html2Txt: function (data) { return _resumeSpace(_resumeBrace(data)); } }; })();
在我的命名空間下定義了htmlFilter方法,然後最後暴露兩個方法Html2Txt和Txt2Html給使用者。
調用的代碼:
<script type="text/javascript"> $(function () { $("#convert").click(function () { var txt = ZhangHongYang.htmlFilter.txt2Html($("#taContent").val()); console.log(txt); $("#divContent").html(txt); $("#taEdit").val(ZhangHongYang.htmlFilter.html2Txt(txt)); }); }); </script>
:
能夠看到換行、空格、以及惡意的HTML代碼等都得到了非常好的在DIV中的顯示。且終於可還原為Textarea中供編輯;假設各位項目中沒有考慮到這類問題,首先你能夠測試下問題,然後能夠使用上面的代碼解決這類問題。
6、單例寫法提高多分支代碼效率
相信大家都瞭解過ajax,對象ajax肯定離不開XMLHttpRequest。並且不同版本號碼、類型的瀏覽器建立方式不一致。
一般我們可能會這麼寫建立XMLHttpRequest的方法:
function createXhr() { var xmlhttp; if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } return xmlhttp ; }
存在一個問題,每次建立XHR對象都須要進行分支推斷,假設某個方法分支特別多,我們能夠做進一步的最佳化,當瀏覽器載入js檔案時,就決定以後調用僅僅會用當中合適的方式,而不會走分支。
我們把代碼改成:
/** * 用於在程式載入次js檔案時,依據當前瀏覽器返回一個建立xhr的Factory 方法,而不須要每次都去分支推斷 */ ZhangHongYang.xhrFactroy = (function () { function _ieCreateXhr() { // code for IE6, IE5 return new ActiveXObject("Microsoft.XMLHTTP"); } function _newCreateXhr() { // code for IE7+, Firefox, Chrome, Opera, Safari return new XMLHttpRequest(); } if (window.XMLHttpRequest) { return _newCreateXhr; } else { return _ieCreateXhr; } })();
當程式載入完畢js檔案後,會自己主動依據瀏覽器類型返回適合的方法,避免每次都會進行分支推斷,我們僅僅須要使用ZhangHongYang.xhrFactroy();建立XHR對象。
7、單例引入懶載入功能
上述的js的檔案基本在引入頁面後,瀏覽器載入就會進行大量操作佔用記憶體,有時候我們希望等到我們去使用時再去運行一些操作。假設從未使用就省去不必要的記憶體消耗,我們能夠進行例如以下改寫代碼:
/** * 用於在程式載入次js檔案時,依據當前瀏覽器返回一個建立xhr的Factory 方法,而不須要每次都去分支推斷 */ ZhangHongYang.xhrFactroy = (function () { var _instance = null; function _constructor() { function _ieCreateXhr() { // code for IE6, IE5 return new ActiveXObject("Microsoft.XMLHTTP"); } function _newCreateXhr() { // code for IE7+, Firefox, Chrome, Opera, Safari return new XMLHttpRequest(); } if (window.XMLHttpRequest) { return _newCreateXhr; } else { return _ieCreateXhr; } } return {getInstance: function () { if (_instance == null) { _instance = _constructor(); } return _instance; }}; })();
<script type="text/javascript"> var xhrFactoryMethod = ZhangHongYang.xhrFactroy.getInstance(); console.log(xhrFactoryMethod()); </script>
僅僅有使用時才會去運行_constructor()方法,而不是我們之前的一載入完畢就運行。
好了。js的單例模式已經經常使用的方法介紹完了。以後在書寫js代碼時,能夠嘗試使用上述的方法進行書寫,而不是大量定義全域function以及變數。請不要在html標籤中添加事件處理的代碼~
假設存在不論什麼問題,或者有不論什麼問題請留言~
著作權聲明:本文部落格原創文章,部落格,未經同意,不得轉載。
Javascript 設計模式 辛格爾頓