zoukankan      html  css  js  c++  java
  • 谈JavaScript代码封装

    前言

    也算老生常谈的问题了,再深入搞一搞怎么玩儿封装,如果看到这篇文章的你,正好你也是追求完美的代码洁癖狂者,那么这篇文章相信非常适合你。

    举一个例子,编写一个Person类,具有name和birthday(时间戳)两个属性及对应的getter和setter方法,注意,setBirthday输入的参数是日期字符串,如"2016-04-08"。getBirthday同样得到的也是日期字符串。那么这个类是这样的——

    var Person = function(name, birthday) {
        this.name = name;
        this.birthday = birthday;   // timestamp
    };
    
    function getTimestampOfInput(dateString) {
        return new Date(dateString).getTime();
    }
    
    function getFormattedDay(timestamp) {
        var datetime = new Date(timestamp);
        var year = datetime.getFullYear();
        var month = datetime.getMonth() + 1;
        var date = datetime.getDate();
        return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                + (String(date).length < 2 ? "0" + date : date);
    }
    
    Person.prototype = {
        setName: function(name) {
            this.name = name;
        },
        getName: function() {
            return this.name;
        },
        /**
         * 设置生日
         * @param dateString
         */
        setBirthday: function(dateString) {
            this.birthday = getTimestampOfInput(dateString);
        },
        /**
         * 获取生日
         * @returns {*}
         */
        getBirthday: function() {
            return getFormattedDay(this.birthday);
        }
    };

    如果采用面向过程的方式去写,我们需要借助自执行匿名函数闭包的方式,如——

    // 常用模式一:单例/静态 - 私有变量&共有方法
    // 生成一个人
    var person = (function() {
        // 私有变量
        var name = '';
        var birthday = new Date().getTime();    // 默认是时间戳方式
        // 共有方法
        return {
            setName: function(newName) {
                name = newName;
            },
            getName: function() {
                return name;
            },
            setBirthday: function(dateString) {
                // 私有函数
                function getTimestampOfInput() {
                    return new Date(dateString).getTime();
                }
    
                birthday = getTimestampOfInput();
            },
            getBirthday: function() {
                return getFormattedDay(birthday);
    
                // 函数式 - 不访问外界变量,没有闭包的呈现
                // 有了输入,便有了预想中的输出,不保存状态
                // 私有函数 - 已工具方法存在
                function getFormattedDay(timestamp) {
                    var datetime = new Date(timestamp);
                    var year = datetime.getFullYear();
                    var month = datetime.getMonth() + 1;
                    var date = datetime.getDate();
                    return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                            + (String(date).length < 2 ? "0" + date : date);
                }
            }
        };
    })();
    
    person.setName('king');
    console.log(person.getName());
    
    person.setBirthday('2016-4-8');
    console.log(person.getBirthday());

    一、精分面向过程的写法

    要知道,上面的面向过程person是一个单例,这种写法更像是一种命名空间提供工具函数的方式,如——

      1 /**
      2  * @file cookie
      3  * @author
      4  */
      5 define(function (require, exports, module) {
      6 
      7     /**
      8      * 操作 cookie
      9      *
     10      * 对外暴露三个方法:
     11      *
     12      * get()
     13      * set()
     14      * remove()
     15      *
     16      * 使用 cookie 必须了解的知识:
     17      *
     18      * 一枚 cookie 有如下属性:
     19      *
     20      *    key value domain path expires secure
     21      *
     22      *    domain: 浏览器只向指定域的服务器发送 cookie,默认是产生 Set-Cookie 响应的服务器的主机名
     23      *    path: 为特定页面指定 cookie,默认是产生 Set-Cookie 响应的 URL 的路径
     24      *    expires: 日期格式为(Weekday, DD-MON-YY HH:MM:SS GMT)唯一合法的时区是 GMT,默认是会话结束时过期
     25      *    secure: 使用 ssl 安全连接时才会发送 cookie
     26      *
     27      * 有点类似命名空间的意思
     28      *
     29      */
     30 
     31     'use strict';
     32 
     33     /**
     34      * 一小时的毫秒数
     35      *
     36      * @inner
     37      * @const
     38      * @type {number}
     39      */
     40     var HOUR_TIME = 60 * 60 * 1000;
     41 
     42     /**
     43      * 把 cookie 字符串解析成对象
     44      *
     45      * @inner
     46      * @param {string} cookieStr 格式为 key1=value1;key2=value2;
     47      * @return {Object}
     48      */
     49     function parse(cookieStr) {
     50 
     51         if (cookieStr.indexOf('"') === 0) {
     52             // 如果 cookie 按照 RFC2068 规范进行了转义,要转成原始格式
     53             cookieStr = cookieStr.slice(1, -1)
     54                                  .replace(/\"/g, '"')
     55                                  .replace(/\\/g, '\');
     56         }
     57 
     58         var result = { };
     59 
     60         try {
     61             // Replace server-side written pluses with spaces.
     62             // If we can't decode the cookie, ignore it, it's unusable.
     63             // If we can't parse the cookie, ignore it, it's unusable.
     64             cookieStr = decodeURIComponent(cookieStr.replace(/+/g, ' '));
     65 
     66             $.each(
     67                 cookieStr.split(';'),
     68                 function (index, part) {
     69                     var pair = part.split('=');
     70                     var key = $.trim(pair[0]);
     71                     var value = $.trim(pair[1]);
     72 
     73                     if (key) {
     74                         result[key] = value;
     75                     }
     76                 }
     77             );
     78         }
     79         catch (e) { }
     80 
     81         return result;
     82     }
     83 
     84     /**
     85      * 设置一枚 cookie
     86      *
     87      * @param {string} key
     88      * @param {string} value
     89      * @param {Object} options
     90      */
     91     function setCookie(key, value, options) {
     92 
     93         var expires = options.expires;
     94 
     95         if ($.isNumeric(expires)) {
     96             var hours = expires;
     97             expires = new Date();
     98             expires.setTime(expires.getTime() + hours * HOUR_TIME);
     99         }
    100 
    101         document.cookie = [
    102             encodeURIComponent(key), '=', encodeURIComponent(value),
    103             expires ? ';expires=' + expires.toUTCString() : '',
    104             options.path ? ';path=' + options.path : '',
    105             options.domain ? ';domain=' + options.domain : '',
    106             options.secure ? ';secure' : ''
    107         ].join('');
    108     }
    109 
    110     /**
    111      * 读取 cookie 的键值
    112      *
    113      * 如果不传 key,则返回完整的 cookie 键值对象
    114      *
    115      * @param {string=} key
    116      * @return {string|Object|undefined}
    117      */
    118     exports.get = function (key) {
    119         var result = parse(document.cookie);
    120         return $.type(key) === 'string' ? result[key] : result;
    121     };
    122 
    123     /**
    124      * 写入 cookie
    125      *
    126      * @param {string|Object} key 如果 key 是 string,则必须传 value
    127      *                            如果 key 是 Object,可批量写入
    128      * @param {*=} value
    129      * @param {Object=} options
    130      * @property {number=} options.expires 过期小时数,如 1 表示 1 小时后过期
    131      * @property {string=} options.path 路径,默认是 /
    132      * @property {string=} options.domain 域名
    133      * @property {boolean=} options.secure 是否加密传输
    134      */
    135     exports.set = function (key, value, options) {
    136 
    137         if ($.isPlainObject(key)) {
    138             options = value;
    139             value = null;
    140         }
    141 
    142         options = $.extend({ }, exports.defaultOptions, options);
    143 
    144         if (value === null) {
    145             $.each(
    146                 key,
    147                 function (key, value) {
    148                     setCookie(key, value, options);
    149                 }
    150             );
    151         }
    152         else {
    153             setCookie(key, value, options);
    154         }
    155     };
    156 
    157     /**
    158      * 删除某个 cookie
    159      *
    160      * @param {string} key
    161      * @param {Object=} options
    162      * @property {string=} options.path cookie 的路径
    163      * @property {string=} options.domain 域名
    164      * @property {boolean=} options.secure 是否加密传输
    165      */
    166     exports.remove = function (key, options) {
    167 
    168         if (key == null) {
    169             return;
    170         }
    171 
    172         options = options || { };
    173         options.expires = -1;
    174 
    175         setCookie(
    176             key,
    177             '',
    178             $.extend({ }, exports.defaultOptions, options)
    179         );
    180     };
    181 
    182     /**
    183      * 默认属性,暴露给外部修改
    184      *
    185      * @type {Object}
    186      */
    187     exports.defaultOptions = {
    188         path: '/'
    189     };
    190 
    191 });
    View Code

    对于这个person单例或者理解为一个普通的(命名空间)对象,我们会发现两个工具函数(用于birthday的格式化)——

    getTimestampOfInput:服务于setBirthday这个方法
    getFormattedDay:服务于getBirthday这个方法

    1.1 将工具函数私有性封装,利用闭包缓存该工具函数

    会发现,每一次执行setBirthday,都会创建getTimestampOfInput这个函数,执行完setBirthday之后,getTimestampOfInput又会被销毁;同理getFormattedDay方法。私有性,我们做到了,但是每一次都需要去创建工具函数(getTimestampOfInput和getFormattedDay)。如果我们想把工具函数仅仅执行一次,可以这样写——

    // 常用模式一:单例/静态 - 私有变量&共有方法
    // 生成一个人
    var person = (function() {
        // 私有变量
        var name = '';
        var birthday = new Date().getTime();    // 默认是时间戳方式
        // 共有方法
        return {
            setName: function(newName) {
                name = newName;
            },
            getName: function() {
                return name;
            },
            setBirthday: (function() {
                // 私有函数
                function getTimestampOfInput(dateString) {
                    return new Date(dateString).getTime();
                }
                return function(dateString) {
                    getTimestampOfInput(dateString);
                };
            })(),
            getBirthday: (function() {
                // 函数式 - 不访问外界变量,没有闭包的呈现
                // 有了输入,便有了预想中的输出,不保存状态
                // 私有函数 - 已工具方法存在
                function getFormattedDay(timestamp) {
                    var datetime = new Date(timestamp);
                    var year = datetime.getFullYear();
                    var month = datetime.getMonth() + 1;
                    var date = datetime.getDate();
                    return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                            + (String(date).length < 2 ? "0" + date : date);
                }
                return function() {
                    return getFormattedDay(birthday);
                };
            })()
        };
    })();

    要看见里面用了一层闭包哦,也就是多需要耗损内存,但换来了性能上的优化。

    1.2 将工具函数抽取为私有

    我们继续变态的走下去,把这两个工具函数抽取出来,如——

    // 常用模式一:单例/静态 - 私有变量&共有方法
    // 生成一个人
    var person = (function() {
        // 私有变量
        var name = '';
        var birthday = new Date().getTime();    // 默认是时间戳方式
        // 函数式 - 不访问外界变量,没有闭包的呈现
        // 有了输入,便有了预想中的输出,不保存状态
        // 私有函数 - 已工具方法存在
        function getFormattedDay(timestamp) {
            var datetime = new Date(timestamp);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1;
            var date = datetime.getDate();
            return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                    + (String(date).length < 2 ? "0" + date : date);
        }
        // 函数式 - 不访问外界变量,没有闭包的呈现
        // 有了输入,便有了预想中的输出,不保存状态
        // 私有函数 - 已工具方法存在
        function getTimestampOfInput(dateString) {
            return new Date(dateString).getTime();
        }
        // 共有方法
        return {
            setName: function(newName) {
                name = newName;
            },
            getName: function() {
                return name;
            },
            setBirthday: function(dateString) {
                birthday = getTimestampOfInput(dateString);
            },
            getBirthday: function() {
                return getFormattedDay(birthday);
            }
        };
    })();

    那么这两个工具方法同样具有私有性,但是它能够服务的方法就更多了,所有对外暴露的方法(如将来有个新的方法getCreateDay),都可以使用这两个工具函数。

    1.3 将工具函数显示声明为私有

    OK,我们看到上面的例子中,name,birthday,包含两个工具方法都是私有的,我们可以使用"_"的方式来显示声明它是私有的,就可以这样去改装——

    // 常用模式一:静态私有变量&共有方法
    // 生成一个人
    var person = {
        // 单例的私有属性 - 或者可理解为静态变量
        _name: '',
        // 单例的私有属性 - 或者可理解为静态变量
        _birthday: new Date().getTime(),    // 默认是时间戳方式
        // 工具函数
        _getTimestampOfInput: function(dateString) {
            return new Date(dateString).getTime();
        },
        // 工具函数
        _getFormattedDay: function(timestamp) {
            var datetime = new Date(timestamp);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1;
            var date = datetime.getDate();
            return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                    + (String(date).length < 2 ? "0" + date : date);
        },
        // 共有方法
        setName: function(newName) {
            this._name = newName;
        },
        getName: function() {
            return this._name;
        },
        setBirthday: function(dateString) {
            this._birthday = this._getTimestampOfInput(dateString);
        },
        getBirthday: function() {
            return this._getFormattedDay(this._birthday);
        }
    };

    看起来还不错,但是私有属性还是可以被访问的,如person._birthday,

    1.4 利用private和public命名空间来实现私有和共有

    那么,我们想要让私有的属性达到真正的私有,并借助命名空间的方式,会有这个方式——

    // 常用模式一:静态私有变量&共有方法
    // 生成一个人
    var person = (function() {
        // 该对象保存静态属性
        // 保存单例的状态
        var _private = {
            // 单例的私有属性 - 或者可理解为静态变量
            _name: '',
            // 单例的私有属性 - 或者可理解为静态变量
            _birthday: new Date().getTime(),    // 默认是时间戳方式
            // 工具函数
            getTimestampOfInput: function(dateString) {
                return new Date(dateString).getTime();
            },
            // 工具函数
            _getFormattedDay: function(timestamp) {
                var datetime = new Date(timestamp);
                var year = datetime.getFullYear();
                var month = datetime.getMonth() + 1;
                var date = datetime.getDate();
                return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                        + (String(date).length < 2 ? "0" + date : date);
            },
            getFormattedDayOfBirthday: function() {
                return this._getFormattedDay(this._birthday);
            }
        };
    
        // 共有对象
        var _public = {
            setName: function(newName) {
                _private._name = newName;
            },
            // 直接从_private对象中获取
            getName: function() {
                return _private._name;
            },
            /**
             * 可直接操作_private中的静态属性
             * @param dateString
             */
            setBirthday: function(dateString) {
                _private._birthday = _private.getTimestampOfInput(dateString);
            },
            getBirthday: function() {
                return _private.getFormattedDayOfBirthday();
            }
        };
    
        return _public;
    })();

    _private和_public这两个命名空间还不错。在此基础上,建议把工具函数拿出来,可以这样——

    // 常用模式一:静态私有变量&共有方法
    // 生成一个人
    var person = (function() {
    
        // 工具函数
        // 可供_private和_public对象共用
        function getTimestampOfInput(dateString) {
            return new Date(dateString).getTime();
        }
        // 工具函数
        // 可供_private和_public对象共用
        function getFormattedDay(timestamp) {
            var datetime = new Date(timestamp);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1;
            var date = datetime.getDate();
            return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                    + (String(date).length < 2 ? "0" + date : date);
        }
    
        // 该对象保存静态属性
        // 保存单例的状态
        var _private = {
            // 单例的私有属性 - 或者可理解为静态变量
            _name: '',
            // 单例的私有属性 - 或者可理解为静态变量
            _birthday: new Date().getTime()    // 默认是时间戳方式
        };
    
        // 共有对象
        var _public = {
            setName: function(newName) {
                _private._name = newName;
            },
            // 直接从_private对象中获取
            getName: function() {
                return _private._name;
            },
            /**
             * 可直接操作_private中的静态属性
             * @param dateString
             */
            setBirthday: function(dateString) {
                _private._birthday = getTimestampOfInput(dateString);
            },
            getBirthday: function() {
                return getFormattedDay(_private._birthday);
            }
        };
    
        return _public;
    })();

    1.5 将工具函数就近于它的调用者

    有些同学非常喜欢将工具函数靠近与它的调用者,类似于这样——

    // 常用模式一:静态私有变量&共有方法
    // 生成一个人
    var person = (function() {
    
        // 该对象保存静态属性
        // 保存单例的状态
        var _private = {
            // 单例的私有属性 - 或者可理解为静态变量
            _name: '',
            // 单例的私有属性 - 或者可理解为静态变量
            _birthday: new Date().getTime()    // 默认是时间戳方式
        };
    
        _private.name = '';
        _private.birthday = new Date().getTime();    // 默认是时间戳方式
    
        var _public = {};
    
        _public.setName = function(newName) {
            _private._name = newName;
        };
    
        _public.getName = function() {
            return _private._name;
        };
    
        // 工具函数
        // 可供_private和_public对象共用
        function getTimestampOfInput(dateString) {
            return new Date(dateString).getTime();
        }
        _public.setBirthday = function(dateString) {
            _private._birthday = getTimestampOfInput(dateString);
        };
    
        // 工具函数
        // 可供_private和_public对象共用
        function getFormattedDay(timestamp) {
            var datetime = new Date(timestamp);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1;
            var date = datetime.getDate();
            return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                    + (String(date).length < 2 ? "0" + date : date);
        }
        _public.getBirthday = function() {
            return getFormattedDay(_private._birthday);
        };
    
        return _public;
    })();

    1.6 将工具函数放入util等全局命名空间

    同样的,我们发现这两个工具函数具有通用性,可以放置于全局,供所有函数使用,那么就有这样的方式,如——

    // 这里的工具类,可以以单独文件存在,供全局工程来使用
    var util = {
        /**
         * 生日格式化显示
         * @param timestamp
         * @returns {string}
         * @private
         */
        getFormattedDay: function(timestamp) {  // 模拟实现静态方法
            var datetime = new Date(timestamp);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1;
            var date = datetime.getDate();
            return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                    + (String(date).length < 2 ? "0" + date : date);
        },
        /**
         * 根据用户输入来获取时间戳,如输入'1995-10-05'
         * @param timestamp
         * @returns {string}
         * @private
         */
        getTimestampOfInput: function(dateString) {
            return new Date(dateString).getTime();
        }
    };
    
    var person = (function() {
        // 私有变量
        var name = '';
        var birthday = new Date().getTime();    // 默认是时间戳方式
        // 共有方法
        return {
            setName: function(newName) {
                name = newName;
            },
            getName: function() {
                return name;
            },
            setBirthday: function(dateString) {
                birthday = util.getTimestampOfInput(dateString);
            },
            getBirthday: function() {
                return util.getFormattedDay(birthday);
            }
        };
    })();

    上面这种方式,也是我们最常用的方式,很直观,易维护。

    OK,那么面向过程的写法方式,就算是精分完了,很变态对不对?

    总之,没有严格的对错,按照你认同喜欢的模式来。下面精分一下面向对象的写法。

    二、精分面向对象的写法

    面向对象的写法,要注意prototype中的方法供所有实例对象所共有,且这里的方法都是对实例状态变更的说明,即对实例属性的操作的变更。

    2.1 不要把工具函数放入prototype中

    基于前言里面的例子,我们常常不注意的将工具函数也都放在prototype当中,如——

    // 多实例
    var Person = function(name, birthday) {
        this.name = name;
        this.birthday = birthday;   // timestamp
    };
    Person.prototype = {
        setName: function(name) {
            this.name = name;
        },
        getName: function() {
            return this.name;
        },
        /**
         * 设置生日
         * @param dateString
         */
        setBirthday: function(dateString) {
            this.birthday = this._getTimestampOfInput(dateString);
        },
        // 工具函数
        _getTimestampOfInput: function(dateString) {
            return new Date(dateString).getTime();
        },
        /**
         * 获取生日
         * @returns {*}
         */
        getBirthday: function() {
            return this._getFormattedDay(this.birthday);
        },
        // 工具函数
        _getFormattedDay: function(timestamp) {
            var datetime = new Date(timestamp);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1;
            var date = datetime.getDate();
            return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                    + (String(date).length < 2 ? "0" + date : date);
        }
    };

    会看见上面的_getTimestampOfInput和_getFormattedDay两个方法也都放置在了prototype当中,然而这里的方法并没有操作实例属性,因此不应该将这类工具方法置于prototype当中。

    2.2 不要将缓存变量放入this当中

    还有一个大家常常犯的一个大错误,就是习惯性把各个方法间通讯的变量放入到this当中,如下——

    var Person = function(name, birthday) {
        this.name = name;
        this.birthday = birthday;   // timestamp
    };
    
    function getTimestampOfInput(dateString) {
        return new Date(dateString).getTime();
    }
    
    function getFormattedDay(timestamp) {
        var datetime = new Date(timestamp);
        var year = datetime.getFullYear();
        var month = datetime.getMonth() + 1;
        var date = datetime.getDate();
        return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                + (String(date).length < 2 ? "0" + date : date);
    }
    
    Person.prototype = {
        setName: function(name) {
            this.name = name;
        },
        getName: function() {
            return this.name;
        },
        /**
         * 设置生日
         * @param dateString
         */
        setBirthday: function(dateString) {
            this.birthday = getTimestampOfInput(dateString);
        },
        /**
         * 获取生日
         * @returns {*}
         */
        getBirthday: function() {
            // 不要把缓存变量放置于this中
            this.birthdayOfFormatted = getFormattedDay(this.birthday);
            return this.birthdayOfFormatted;
        }
    };

    会看到,这里的this.birthdayOfFormatted是一个缓存变量,并不能代表这个实例的某个状态。好了,我们回到正确的方式。

    2.3 将工具函数就近于方法的调用者

    // 多实例 - 抽取工具函数
    var Person = function(name, birthday) {
        this.name = name;
        this.birthday = birthday;   // timestamp
    };
    
    Person.prototype.setName = function(name) {
        this.name = name;
    };
    
    Person.prototype.getName = function() {
        return this.name;
    };
    
    // 工具函数
    function getTimestampOfInput(dateString) {
        return new Date(dateString).getTime();
    }
    
    Person.prototype.setBirthday = function(dateString) {
        this.birthday = getTimestampOfInput(dateString);
    };
    
    // 工具函数
    function getFormattedDay(timestamp) {
        var datetime = new Date(timestamp);
        var year = datetime.getFullYear();
        var month = datetime.getMonth() + 1;
        var date = datetime.getDate();
        return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                + (String(date).length < 2 ? "0" + date : date);
    }
    
    Person.prototype.getBirthday = function() {
        return getFormattedDay(this.birthday);
    };

    在维护性方面略胜一筹,主要看个人的变成习惯。

    2.4 将工具函数放入类命名空间中,充当类的静态函数

    // 多实例 - 抽取工具函数
    var Person = function(name, birthday) {
        this.name = name;
        this.birthday = birthday;   // timestamp
    };
    
    // 工具函数 - 对外静态变量
    Person.getTimestampOfInput = function (dateString) {
        return new Date(dateString).getTime();
    };
    
    // 工具函数 - 对外静态变量
    Person.getFormattedDay = function(timestamp) {
        var datetime = new Date(timestamp);
        var year = datetime.getFullYear();
        var month = datetime.getMonth() + 1;
        var date = datetime.getDate();
        return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                + (String(date).length < 2 ? "0" + date : date);
    };
    
    Person.prototype = {
        setName: function(name) {
            this.name = name;
        },
        getName: function() {
            return this.name;
        },
        /**
         * 设置生日
         * @param dateString
         */
        setBirthday: function(dateString) {
            this.birthday = Person.getTimestampOfInput(dateString);
        },
        /**
         * 获取生日
         * @returns {*}
         */
        getBirthday: function() {
            return Person.getFormattedDay(this.birthday);
        }
    };

    我个人比较推荐这种写法,当然也可以把工具函数放入某个类似于util的命名空间中,供全局调用。

    2.5 将工具函数放入util等全局命名空间

    // 这里的工具类,可以以单独文件存在,供全局工程来使用
    var util = {
        /**
         * 生日格式化显示
         * @param timestamp
         * @returns {string}
         * @private
         */
        getFormattedDay: function(timestamp) {  // 模拟实现静态方法
            var datetime = new Date(timestamp);
            var year = datetime.getFullYear();
            var month = datetime.getMonth() + 1;
            var date = datetime.getDate();
            return year + '-' + (String(month).length < 2 ? "0" + month : month) + "-"
                    + (String(date).length < 2 ? "0" + date : date);
        },
        /**
         * 根据用户输入来获取时间戳,如输入'1995-10-05'
         * @param timestamp
         * @returns {string}
         * @private
         */
        getTimestampOfInput: function(dateString) {
            return new Date(dateString).getTime();
        }
    };
    
    
    // 多实例 - 抽取工具函数
    var Person = function(name, birthday) {
        this.name = name;
        this.birthday = birthday;   // timestamp
    };
    
    Person.prototype = {
        setName: function(name) {
            this.name = name;
        },
        getName: function() {
            return this.name;
        },
        /**
         * 设置生日
         * @param dateString
         */
        setBirthday: function(dateString) {
            this.birthday = util.getTimestampOfInput(dateString);
        },
        /**
         * 获取生日
         * @returns {*}
         */
        getBirthday: function() {
            return util.getFormattedDay(this.birthday);
        }
    };

    好啦,整个面向对象的写法方式介绍到这儿。

    总之,归于一点——要知道什么方法可以当做工具函数处理,并合理地放置工具函数的位置。

    三、总结

    整篇文章主要围绕工具函数的写法展开,模式不同,没有对与错,依照自身的编码习惯而定。欢迎看到文章的博友补充。

  • 相关阅读:
    cmake自动添加宏定义
    Wapiti web扫描工具使用——支持ssl,看官方示例报告就知道如何支持带cookie和用户名密码的扫描了
    AI入门(重实践)书籍推荐
    初探零信任模型——就是假设所有的设备、人员等都是不可信的,在此基础上构建安全策略
    概率论疑难问题---7、通俗理解最小二乘法
    概率论疑难问题---6、极大似然估计
    概率论疑难问题---5、通俗理解中心极限定理
    matplotlib画直方图
    numpy数组添加元素
    概率论疑难问题---4、通俗理解概率论中的“矩”
  • 原文地址:https://www.cnblogs.com/jinguangguo/p/5369076.html
Copyright © 2011-2022 走看看