js比较器组件Comparator.js

来源:互联网 发布:js判断哪个tr被双击 编辑:程序博客网 时间:2024/05/28 23:09

比较器

在平常的业务中,值比较不仅仅是“==”或“===”,而是具有业务意义的值比较,比如查询条件的比较,数组值比较和业务日期的值比较等等。在编译语言中,例如java,可以重写hashcode和equal方法来进行引用类型比较,而基本类型比较则通过“==”来进行比较,那么js中是否可以这么做?当然可以,前提是在Object.prototype中添加hashcode和equal方法,但这种方式存在对象属性引入,容易造成未知属性污染。所以比较器组件Comparator.js,在进行组件式开发中,就尤其有用。


Comparator.js

    var class2type = {}, toString = class2type.toString,         map2type = {            "string": ["boolean", "number", "date", "regexp"],            "number": ["string", "boolean"],            "array": "object",            "date": "string",            "regexp": "string"        };        //遍历数组元素进行处理.        function each(args, cb) {            var i = 0, len = args.length;            for(; i < len; i++) {                cb(i, args[i]);            }        }        //两个类型比较.        function _compare(src, target) {            if(src === target) return true;             var srcType = class2type[toString.call(src)], targetType = class2type[toString.call(target)];            //类型相同时            if(srcType === targetType) {                if(srcType === "string" || srcType === "number" || srcType === "boolean") {                    return src === target;                } else if(srcType === "object") {                    return this.compareObject(src, target);                } else if(srcType === "array") {                    return this.compareArray(src, target);                } else if(srcType === "date") {                    return this.compareDate(src, target);                } else if(srcType === "regexp") {                    return this.compareRegExp(src, target);                }            //类型可以比较时               } else if(this.canComparable(srcType, targetType)) {                if(srcType === "string") {                    if(targetType === "boolean") {                        return this.compareBoolean(src, target);                    } else if(targetType === "number") {                        return src === String(target);                      } else if(targetType === "date") {                        return this.compareDate(src, target);                       } else if(targetType === "regexp") {                        return this.compareRegExp(src, target);                     }                } else if(srcType === "number") {                    return this.compareNumber(Number(src), Number(target));                } else if(srcType === "array") {                    return this.compareArray(src, target);                } else if(srcType === "date") {                    return this.compareDate(src, target);                } else if(srcType === "regexp") {                    return this.compareRegExp(src, target);                }            }            return false;        }        //时间比较, 只能比较到日.        function _compareDate(dSrc, dTarget) {            var srcType = class2type[toString.call(dSrc)],                 targetType = class2type[toString.call(dTarget)];            if(srcType === targetType) {                return _dateFormat(dSrc, "yyyy-MM-dd") === _dateFormat(dTarget, "yyyy-MM-dd");              } else if(srcType === "date") {                return _dateFormat(dSrc, "yyyy-MM-dd") === dTarget;             } else if(srcType === "string") {                return dSrc === _dateFormat(dTarget, "yyyy-MM-dd");             }               }        //格式化日期显示.       function _dateFormat(date, fmtStr) {            if(!fmtStr || typeof fmtStr != "string") return date;            var fmt = { //按字母分开                "M+": date.getMonth() + 1, //月                "d+": date.getDate(), //日                "h+": date.getHours(), //时                "m+": date.getMinutes(), //分                "s+": date.getSeconds(), //秒                "q+": Math.floor(date.getMonth() + 3) / 3, //季度                "S": date.getMilliseconds() //毫秒             };            date = typeof date === "string" && new Date(+String(date.match(/\d+/))) ||                 typeof date === "number" && new Date(date) || new Date();            fmtStr = /(y+)/.test(fmtStr) && fmtStr.replace(RegExp.$1,                 (date.getFullYear() + "").substr(4 - RegExp.$1.length)) || fmtStr;            for(var k in fmt) {                if(new RegExp("(" + k + ")").test(fmtStr)) {                    fmtStr = fmtStr.replace(RegExp.$1, RegExp.$1.length == 1 ? fmt[k] :                         ("00" + fmt[k]).substr(("" + fmt[k]).length));                }            }            return fmtStr;        }        //正则表达式比较.        function _compareRegExp(eSrc, eTarget) {            var srcType = class2type[toString.call(eSrc)],                 targetType = class2type[toString.call(eTarget)];            if(srcType === targetType) {                return eSrc.source === eTarget.source;            } else if(srcType === "string") {                return eSrc === eTarget.source;            } else if(srcType === "regexp") {                return eSrc.source === eTarget;            }               }        //布尔类型值比较.        function _compareBoolean(iSrc, iTarget) {            var srcType = class2type[toString.call(iSrc)],                 targetType = class2type[toString.call(iTarget)];            if(srcType === "string") {                iSrc = iSrc.replace(/\s+/g, "");            }            if(iTarget === "string") {                iTarget = iTarget.replace(/\s+/g, "");            }            return Boolean(iSrc) === Boolean(iTarget);        }        //两个数组进行比较.        function _compareArray(srcArr, targetArr) {            if(srcArr.length != targetArr.length) {                return false;            }            if(srcArr.sort) {                srcArr.sort();            }            if(targetArr.sort) {                targetArr.sort();            }            for(var i = 0, len = srcArr.length; i < len; i++) {                if(srcArr[i] != targetArr[i] && !this.compare(srcObj[name], targetObj[name])) {                    return false;                }            }            return true;        }        //两个对象进行值比较.        function _compareObject(srcObj, targetObj) {            var srcProps = [], targetProps = [], name = null;            for(name in srcObj) srcProps.push(name);            for(name in targetObj) targetProps.push(name);            if(srcProps.length != targetProps.length) {                return false;            }            for(name in srcObj) {                if(srcObj[name] != targetObj[name] && !this.compare(srcObj[name], targetObj[name])) {                    return false;                }            }            return true;        }        //两个类型是否可以比较.        function _canComparable(sType, tType) {            return map2type[sType].indexOf(tType) > -1;        }        //两个数字进行比较, 这里设置精度为8位.        function _compareNumber(srcNum, targetNum) {            return Number(srcNum).toFixed(8) === Number(targetNum).toFixed(8);        }        //类型添加.        each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {            class2type[ "[object " + name + "]" ] = name.toLowerCase();        });        //定义比较器.        var Comparator = {            compare: _compare,            compareArray: _compareArray,            compareBoolean: _compareBoolean,            compareDate: _compareDate,            compareRegExp: _compareRegExp,            compareObject: _compareObject,            compareNumber: _compareNumber,             canComparable: _canComparable,            getInstance: function() {                var comparator = {};                for(var name in this) {                    if(name !== "getInstance" && this[name]) {                        comparator[name] = this[name];                    }                }                return comparator;            }        };        //return Comparator;

测试

<html>    <script type="text/javascript" src="./Comparator.js"></script>    <script>        var obj1 = {name: "a", age: 17}, obj2 = {name: "a", age: 18};        //alert(Comparator.compare(obj1, obj2));        var obj3 = {name: "1", age: 2, person: obj1}, obj4 = {name: "1", age: 2, person: obj2};        alert(Comparator.compare(obj3, obj4));        var date1 = "2017-09-24", date2 = new Date();        //alert(Comparator.compare(date1, date2));        var arr1 = [1,2,3,4,5], arr2 = [1,3,4,2,5];        //alert(Comparator.compare(arr1, arr2));    </script></html>

结论

对js中的基本类型进行值比较,而不是简单的“==”和“===”在业务应用中十分常见,js相对与java来说,缺少hashcode和equal方法,那么以js组件进行api的抽取,来达到通用的值比较则具有一定的实践意义。

原创粉丝点击