javascript學習-類型判斷

javascript學習-類型判斷

1.類型判斷的的武器

javascript中用於類型判斷的武器基本上有如下幾種:javascript

  1. 嚴格相等===,用來判斷null,undefined,true,false這種有限值的數據類型很好用,惟一須要注意的是NaN !== NaN
  2. typeof運算符,用來判斷其他的基本類型很好用
  3. Object.prototype.toString,用來判斷對象類型很好用

2.類型判斷的實現

瞭解了咱們手中的武器,代碼是很是簡單了。固然了,這些函數都是本身測試時用的,不能直接用於商業庫中,畢竟不少兼容性等細節問題沒有考慮:html

// 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.類型判斷的測試

基於咱們的學習傳統,一段測試用例那是必須的。不過首先咱們須要準備測試數據:java

            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; } },
            ];

基本上把咱們可能想到的數據都加上去了,固然你也能夠本身繼續添加。正則表達式

至於爲何用一個對象的形式對測試數據進行了一次包裝?主要是爲了兼容通常的測試用例數據,咱們如今的測試用例不須要檢測測試結果,若是須要的話,那麼測試用例數據通常是:ide

                { 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的,可是我不知道怎麼插入博客中,只好最笨的方式來截圖了:測試

結果固然是測試經過了,若是不經過,我早就悄悄的改了,呵呵。ui

4.測試數據的顯示

原本javascript中如何顯示一個值JSON.stringify之類的函數已經考慮到了。可是這玩意畢竟是給機器看的,而不是給人看的,我不滿意的主要是:this

  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
相關文章
相關標籤/搜索