Javascript 設計模式 辛格爾頓

來源:互聯網
上載者:User

標籤:

轉載請註明出處: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 設計模式 辛格爾頓

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.