zoukankan      html  css  js  c++  java
  • Javascript 设计模式 辛格尔顿

    转载请注明出处: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=" 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代码总体上结构清晰;学习使用面向对象的方式处理问题。



    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=" 400px;height: 120px;" id="taContent">
    </textarea>
    
    <input type="button" id="convert" value="Convert"/>
    <br/>
    <br/>
    
    
    <fieldset style=" 400px">
        <legend>html转化为Txt,供Div展示</legend>
    <div style=" 400px;height: 120px;border: 1px solid #555;" id="divContent">
    
    </div>
    </fieldset>
    
    <br/>
    <br/>
    
    <fieldset style=" 400px">
        <legend>Txt转化为Html,供Textarea改动</legend>
        <textarea style=" 400px;height: 120px;" id="taEdit">
        </textarea>
    </fieldset>
    
    </body>

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

    我们的js代码:

      /**
             * 对用户在TextArea中输入的数据进行过滤,把< -> <等操作,以及逆向操作
             */
            ZhangHongYang.htmlFilter = (function ()
            {
                /**
                 * 转化textarea中的空格为$nbsp;
                 * 
    转化为<br/>
                 * @private
                 */
                function _transSpace(data)
                {
                    return data.replace(/
    /g, "<br/>").replace(/s/g, " ");
                };
    
                /**
                 * 转化全部尖括号
                 * @private
                 */
                function _transBrace(data)
                {
                    return data.replace(/</g, "<").replace(/>/g, ">");
                };
    
    
                function _resumeSpace(data)
                {
                    return data.replace(/ /g, " ").replace(/<brs*/>/ig, "
    ");
                };
                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的工厂方法,而不须要每次都去分支推断
             */
            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的工厂方法,而不须要每次都去分支推断
             */
            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标签中添加事件处理的代码~


    假设存在不论什么问题,或者有不论什么问题请留言~



    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    暑假学习
    暑假学习
    暑假学习
    暑假学习
    暑假学习
    经验教训+总结
    NT 时刻
    联赛模拟测试 17
    联赛模拟测试 16
    联赛模拟测试 15
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4657270.html
Copyright © 2011-2022 走看看