zoukankan      html  css  js  c++  java
  • javascript学习-类型判断

    javascript学习-类型判断

    1.类型判断的的武器

    javascript中用于类型判断的武器基本上有以下几种:

    1. 严格相等===,用来判断null,undefined,true,false这种有限值的数据类型很好用,唯一需要注意的是NaN !== NaN
    2. typeof运算符,用来判断其余的基本类型很好用
    3. Object.prototype.toString,用来判断对象类型很好用

    2.类型判断的实现

    了解了我们手中的武器,代码是非常简单了。当然了,这些函数都是自己测试时用的,不能直接用于商业库中,毕竟很多兼容性等细节问题没有考虑:

    // isType function
    function _isNumber(value) {
        return typeof value === "number";
    }
    
    function _isString(value) {
        return typeof value === "string";
    }
    
    function _isBoolean(value) {
        return typeof value === "boolean";
    }
    
    function _isUndefined(value) {
        // return typeof value === "undefined";
        return value === (void 0);
    }
    
    function _isNull(value) {
        return value === null;
    }
    
    function _isPrimitive(value) {
        return _isNumber(value) || _isString(value) || _isBoolean(value)
            || _isNull(value) || _isUndefined(value);
    }
    
    function _isZero(value) {
        return value === 0;
    }
          
    // Is the given value `NaN`? (NaN is the only number which does not equal itself).
    function _isNaN(value) {
        return _isNumber(value) && value !== value;
    }
    
    function _isInfinity(value) {
        return value === Infinity || value === -Infinity;
    }
    
    function _isFinity(value) {
        return _isNumber(value) && !_isInfinity(value) && !_isNaN(value);
    }
    
    function _isObject(value) {
        return !_isPrimitive(value);
    }
    
    function _isArray(value) {
        // return Array.isArray(value);
        return Object.prototype.toString.call(value) === '[object Array]';
    }
    
    function _isFunction(value) {
        return Object.prototype.toString.call(value) === '[object Function]';
    }
    
    function _isRegExp(value) {
        return Object.prototype.toString.call(value) === '[object RegExp]';
    }
    
    function _isDate(value) {
        return Object.prototype.toString.call(value) === '[object Date]';
    }
    
    function _isError(value) {
        return Object.prototype.toString.call(value) === '[object Error]';
    }
    
    function _isNumberObj(value) {
        return Object.prototype.toString.call(value) 
            === '[object Number]' && !_isNumber(value);
    }
    
    function _isStringObj(value) {
        return Object.prototype.toString.call(value) 
            === '[object String]' && !_isString(value);
    }
    
    function _isBooleanObj(value) {
        return Object.prototype.toString.call(value) 
            === '[object Boolean]' && !_isBoolean(value);
    }
    
    function _isArguments(value) {
        return Object.prototype.toString.call(value) === '[object Arguments]';  
    }

    3.类型判断的测试

    基于我们的学习传统,一段测试用例那是必须的。不过首先我们需要准备测试数据:

                var caseDatas = [
                    // number
                    { sample : NaN },
                    { sample : 0 },
                    { sample : +0 },
                    { sample : -0 },
                    { sample : 1 },
                    { sample : 012 },
                    { sample : 0x12 },
                    { sample : 1.2 },
                    { sample : 1.217e2 },
                    { sample : Infinity },
                    { sample : -1 },
                    { sample : -012 },
                    { sample : -0x12 },
                    { sample : -1.2 },
                    { sample : -1.217e2 },
                    { sample : -Infinity },
                    // string
                    { sample : "" },
                    { sample : "abc" },
                    { sample : "1abc" },
                    { sample : "NaN" },
                    { sample : "0" },
                    { sample : "+0" },
                    { sample : "-0" },
                    { sample : "1" },
                    { sample : "012" },
                    { sample : "0x12" },
                    { sample : "1.2" },
                    { sample : "1.217e2" },
                    { sample : "Infinity" },
                    { sample : "-1" },
                    { sample : "-012" },
                    { sample : "-0x12" },
                    { sample : "-1.2" },
                    { sample : "-1.217e2" },
                    { sample : "-Infinity" },
                    // boolean
                    { sample : true },
                    { sample : false },
                    // remain primitive
                    { sample : null },
                    { sample : undefined },
                    // built-in function
                    { sample : new Object() },
                    { sample : new Array() },
                    { sample : new Function() },
                    { sample : new RegExp() },
                    { sample : new Date() },
                    { sample : new Error() },
                    { sample : new Number() },
                    { sample : new String() },
                    { sample : new Boolean() },
                    // built-in literals
                    { sample : [] },
                    { sample : [1] },
                    { sample : [1,2,3] },
                    { sample : {} },
                    { sample : {name : "wgs", age : 18} },
                    { sample : function() {} },
                    { sample : function(a, b) { return a + b; } },
                ];

    基本上把我们可能想到的数据都加上去了,当然你也可以自己继续添加。

    至于为什么用一个对象的形式对测试数据进行了一次包装?主要是为了兼容一般的测试用例数据,我们现在的测试用例不需要检测测试结果,如果需要的话,那么测试用例数据一般是:

                    { sample : NaN,                 result : false }

    下面来写测试函数:

                function testCase(caseData, fn) {
                    // 得到测试数据的采样值
                    var sample = caseData.sample;
                    // 得到判断函数的结果
                    var isOk = fn(sample);
                    if (isOk) {
                        // 如果判断是这种类型,用_varDesc函数得到值的描述
                        var desc = _varDesc(sample);
                        // 添加到测试节点上,这里当然都是true的
                        assert(isOk, desc);
                    }
                }

    下面写测试代码,对我们的类型判断函数逐个进行测试:

                test("_isNumber", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isNumber);
                    });
                });
    
                test("_isString", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isString);
                    });
                });
    
                test("_isBoolean", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isBoolean);
                    });
                });
    
                test("_isUndefined", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isUndefined);
                    });
                });
    
                test("_isNull", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isNull);
                    });
                });
    
                test("_isZero", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isZero);
                    });
                });
    
                test("_isNaN", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isNaN);
                    });
                });
    
                test("_isInfinity", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isInfinity);
                    });
                });
    
                test("_isFinity", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isFinity);
                    });
                });
    
                test("_isObject", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isObject);
                    });
                });
    
                test("_isArray", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isArray);
                    });
                });
    
                test("_isFunction", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isFunction);
                    });
                });
    
                test("_isRegExp", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isRegExp);
                    });
                });
    
                test("_isDate", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isDate);
                    });
                });
    
                test("_isError", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isError);
                    });
                });
    
                test("_isNumberObj", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isNumberObj);
                    });
                });
    
                test("_isStringObj", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isStringObj);
                    });
                });
    
                test("_isBooleanObj", function() {
                    caseDatas.forEach(function(value) {
                        testCase(value, _isBooleanObj);
                    });
                });

    结果是html的,但是我不知道怎么插入博客中,只好最笨的方式来截图了:

    结果当然是测试通过了,如果不通过,我早就悄悄的改了,呵呵。

    4.测试数据的显示

    本来javascript中如何显示一个值JSON.stringify之类的函数已经考虑到了。但是这玩意毕竟是给机器看的,而不是给人看的,我不满意的主要是:

    1. 对undefined返回undefined,而不是一个字符串,想想也能忍受
    2. 对函数返回undefined,你给我个函数名不是更好吗?
    3. 对NaN,Infinity直接返回null,这个不能忍了

    既然你不提供,那我就自己来吧,所以就有了下面的函数_varDesc,之所以用_开头是为了避免名称冲突,毕竟这个小玩意主要是为了自己用着方便,直接放在全局对象中了,就没必要弄个即时函数啥的吧。

    function _varDesc(value) {
        var ret = "";
        if (_isNumber(value)) {
            ret = "number({0})".fmt(value);
        }
        else if (_isString(value)) {
            ret = "string("{0}")".fmt(value);
        }
        else if (_isBoolean(value)) {
            ret = "boolean({0})".fmt(value);
        }
        else if (_isNull(value)) {
            ret = "null".fmt(value);
        }
        else if (_isUndefined(value)) {
            ret = "undefined";
        }
        else if (_isArray(value)) {
            ret = "Array({0})".fmt(JSON.stringify(value));
        }
        else if (_isFunction(value)) {
            ret = "Function({0})".fmt(value.name);
        }
        else if (_isRegExp(value)) {
            ret = "Regexp({0})".fmt(value.toString());
        }
        else if (_isDate(value)) {
            ret = "Date({0})".fmt(value.toString());
        }
        else if (_isError(value)) {
            ret = "Error({0})".fmt(value.toString());
        }
        else if (_isNumberObj(value)) {
            ret = "Number({0})".fmt(value.toString());
        }
        else if (_isStringObj(value)) {
            ret = "String("{0}")".fmt(value.toString());
        }
        else if (_isBooleanObj(value)) {
            ret = "Boolean({0})".fmt(value.toString());
        }
        else if (_isObject(value)) {
            ret = "Object({0})".fmt(JSON.stringify(value));     
        }
        else {
            ret = "Unknown";
        }   
    
        return ret;
    }

    fmt函数是为了弥补javascript中字符串没有format函数的小缺憾。当然了,这是简化版,充其量就是个正则表达式替换,根本没有考虑显示宽度,显示精度等复杂的格式控制。

    String.prototype.fmt = function(){
        var args = arguments;
        return this.replace(/{(d+)}/g,
            function(m, i){
                return args[i];
            });
    }

     最后,附一个JSON.stringify函数的测试数据吧,别说我是冤枉它的:

                var caseDatas = [
                    // number
                    { sample : NaN,                 result : "null" },
                    { sample : 0,                   result : "0" },
                    { sample : +0,                  result : "0" },
                    { sample : -0,                  result : "0" },
                    { sample : 1,                   result : "1" },
                    { sample : 012,                 result : "10" },
                    { sample : 0x12,                result : "18" },
                    { sample : 1.2,                 result : "1.2" },
                    { sample : 1.217e2,             result : "121.7" },
                    { sample : Infinity,            result : "null" },
                    { sample : -1,                  result : "-1" },
                    { sample : -012,                result : "-10" },
                    { sample : -0x12,               result : "-18" },
                    { sample : -1.2,                result : "-1.2" },
                    { sample : -1.217e2,            result : "-121.7" },
                    { sample : -Infinity,           result : "null" },
                    // string
                    { sample : "",                  result : '""' },
                    { sample : "abc",               result : '"abc"' },
                    { sample : "1abc",              result : '"1abc"' },
                    { sample : "NaN",               result : '"NaN"' },
                    { sample : "0",                 result : '"0"' },
                    { sample : "+0",                result : '"+0"' },
                    { sample : "-0",                result : '"-0"' },
                    { sample : "1",                 result : '"1"' },
                    { sample : "012",               result : '"012"' },
                    { sample : "0x12",              result : '"0x12"' },
                    { sample : "1.2",               result : '"1.2"' },
                    { sample : "1.217e2",           result : '"1.217e2"' },
                    { sample : "Infinity",          result : '"Infinity"' },
                    { sample : "-1",                result : '"-1"' },
                    { sample : "-012",              result : '"-012"' },
                    { sample : "-0x12",             result : '"-0x12"' },
                    { sample : "-1.2",              result : '"-1.2"' },
                    { sample : "-1.217e2",          result : '"-1.217e2"' },
                    { sample : "-Infinity",         result : '"-Infinity"' },
                    // boolean
                    { sample : true,                result : "true" },
                    { sample : false,               result : "false" },
                    // remain primitive
                    { sample : null,                result : "null" },
                    { sample : undefined,           result : undefined },
                    // built-in function
                    { sample : new Object(),        result : "{}" },
                    { sample : new Array(),         result : "[]" },
                    { sample : new Function(),      result : undefined },
                    { sample : new RegExp(),        result : "{}" },
                    { sample : date,                result : '"2016-12-18T00:00:00.000Z"' },
                    { sample : new Error(),         result : "{}" },
                    { sample : new Number(),        result : "0" },
                    { sample : new String(),        result : '""' },
                    { sample : new Boolean(),       result : "false" },
                    // built-in literals
                    { sample : [],                  result : "[]" },
                    { sample : [1],                 result : "[1]" },
                    { sample : [1,2,3],             result : "[1,2,3]" },
                    { sample : {},                  result : "{}" },
                    { sample : person,              result : '{"name":"wgs","age":18}' },
                    { sample : function() {},       result : undefined },
                    { sample : add,                 result : undefined },
                ];
    View Code
  • 相关阅读:
    Linux自定义服务文件编写
    Ubuntu PPA方式安装vim
    ubuntu PPA使用指南
    ubuntu安装最新emacs
    Docker支持中文
    C#调用Go版DLL
    C#调用exe程序
    golang编写动态库供c#程序调用
    科学正在追赶中医,中医将变得时髦(转载)
    常见.NET功能代码汇总 (3)
  • 原文地址:https://www.cnblogs.com/oowgsoo/p/6404117.html
Copyright © 2011-2022 走看看