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

javascript学习-类型判断的更多相关文章

  1. Cocos Creator (JavaScript手机类型判断)

    手机类型判断 var BrowserInfo = { userAgent: navigator.userAgent.toLowerCase() isAndroid: Boolean(navigator ...

  2. 廖雪峰 JavaScript 学习笔记(判断、循环)

    条件判断  固定格式:if () { ... } else { ... } ,else可选 1.多行条件判断,通常把else if连写在一起,来增加可读性 例子: var age = 3; if (a ...

  3. javascript 变量类型判断

    一.typeof 操作符 对于Function, String, Number ,Undefined 等几种类型的对象来说,他完全可以胜任,但是为Array时 "); typeof arr ...

  4. javascript学习代码-判断闰年

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. JavaScript对象类型判断注意点

    注意点 不要使用 new Number() . new Boolean() . new String() 创建包装对象:用 parseInt() 或 parseFloat() 来转换任意类型到numb ...

  6. Javascript学习1 - Javascript中的类型对象

    原文:Javascript学习1 - Javascript中的类型对象 1.1关于Numbers对象. 常用的方法:number.toString() 不用具体介绍,把数字转换为字符串,相应的还有一个 ...

  7. javascript学习笔记(四) Number 数字类型

    数字格式化方法toFixed().toExponential().toPrecision(),三个方法都四舍五入 toFixed() 方法指定小数位个数  toExponential() 方法 用科学 ...

  8. javascript学习-基本类型

    javascript学习-基本类型 1.概述 javascript的数据类型大体上分两种:基本类型和对象类型.简单的区分就是基本类型是无法再分的原子级类型:对象类型是容器,可以容纳基本类型和对象类型. ...

  9. JavaScript学习总结(2)——JavaScript数据类型判断

    最近做项目中遇到了一些关于javascript数据类型的判断处理,上网找了一下资料,并且亲自验证了各种数据类型的判断,在此做一个总结吧! 一.JS中的数据类型  1.数值型(Number):包括整数. ...

随机推荐

  1. 反射技术在Android中的应用

    本博客转自:http://blog.csdn.net/tiefeng0606/article/details/51700866 动态语言: 一般认为在程序运行时,允许改变程序结构或变量类型,这种语言称 ...

  2. MySQL中 InnoDB 和 MyISAM 小结

    转:http://blog.csdn.net/ithomer/article/details/5136982 部分内容: InnoDB和MyISAM的差别 InnoDB和MyISAM是许多人在使用My ...

  3. MySQL show status命令参数

    Aborted_clients         由于客户没有正确关闭连接已经死掉,已经放弃的连接数量.   Aborted_connects 尝试已经失败的MySQL服务器的连接的次数.   Binl ...

  4. Java通过JNI调用dll详细过程(转)

    源:Java通过JNI调用dll详细过程 最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无 ...

  5. JavaScript DOM节点操作总结

    节点类型 节点类型主要有三种:元素节点,属性节点和文本节点. 而对DOM的主要也就是围绕元素节点和属性节点的增删改查.下面就分别从对元素节点的操作和对属性节点的操作来介绍. 元素节点 查 在对DOM进 ...

  6. UVa 10176 - Ocean Deep ! - Make it shallow !!

    题目大意:判断一个很大的二进制能否被131071整除.在二进制转十进制的过程中不断取模,最后判断结果是否是0就可以了. #include <cstdio> #include <cst ...

  7. C# .NET中的 反射的应用

    C#中的映射 C#编译后的文件主要由IL代码和元数据组成,元数据为.NET组件提供了丰富的自描述特性,它使得我们可以在代码运行时获知组件中的类型等重要的信息.C#中这是通过一种称作映射(Reflect ...

  8. jquery textarea输入字符字数提示

    效果: html代码: <textarea id="assayInfo" name="assayInfo" rows="3" cols ...

  9. ZOJ 1012 Mainframe

    题目大意:有一台主机,有m个cpu和n的内存,有l个任务,每个任务需消耗一定的cpu和内存,给出任务的开始时间和截止时间,完成任务可获得一定的金钱,同时提前完成有奖金,延后完成要扣钱.计算到某个时间所 ...

  10. setTimeout,setInterval 最短触发时间

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...