编写可维护的代码规则第2篇。
本篇将来讨论下数据类型检测的较好实践。
首先是空比较的问题,有时会出现将变量与null
值进行比较的情况,例如:
if(val !== null){
val.sort();
val.forEachj(function(){
//执行逻辑代码...
})
}
上例中,可以预见变量val
应该是个数组类型的数据,因为具有sort()
和forEach()
方法,所以在if判断语句中时,用val !== null
来进行判断,并不能完全确认val
就一定是数组类型,因为如果当val
值为string
、number
等时,判断表达示也是为真成立的,此时也会进入到if判断中去。
所以需要寻找更好的值判断方法。
当值为基本数据类型时,比如String
、Number
、Boolean
、undefined
等。可以使用typeof
来对值进行判断。而对于null
,则不适用typeof
,并且null
一般也ぎ建议用于检测语句,null
比较通常不会包含足够的信息以判断值的类型是否合法。但有个例外,如果期望值就是null
,可以使用全等运算符val === null
或非全等运算符val !== null
来检测,另外如果期望值比较模糊,可以为undefined
或者null
,也可以使用val == null
来做检测语句。
当值为引用数据类型时,比如Date
、RegExp
、Error
等,则可以使用instanceof
来作为检测语句。instanceof
可以检测引用数据类型的构造器和原型链。
从技术上讲,函数也是引用类型,同样存在构造函数Function
,每个函数都是它的实例。但函数的检测语句则不用instanceof
,而是使用typeof
,如:
function fn(){};
console.log(typeof fn === "function"); //true
但这里要注意,使用typeof
来检测函数类型有个限制,在IE8及更早版本IE浏览器中,使用typeof
来检测DOM节点(比如document.getElementById()
)中的函数都返回object
,个中原因是浏览器对DOM的实现差异。
至于引用类型中的数组检测,现在有两种比较好的最佳实践:
var arr = [10, 2, 'A'];
console.log(Array.isArray(arr)); //true
Array.isArray()
方法是官方提供的数组检测最佳实践,但目前仍然还有些兼容性问题。IE9+
、FireFox4+
、Safari5+
、opera10.5+
和Chrom
都实现这个方法。
但当浏览器不存在此方法时,就要使用另外一种方法:
Object.prototype.toString.call(arr) === "[object Array]"; //true
这是一种非常优雅的数组检测语句,也是适用性最广的,如果你的代码所处生产环境对兼容性要求较高时,保险起见还是使用这种方法吧。
综合来说,检测数组使用如下方法:
function isArray( arr ){
if( typeof Array.isArray === "function" ){
return Array.isArraya( arr );
}else {
return Object.prototype.toString.call( arr ) === "[object Array]";
}
}
最后再来看下属性检测。检测一个属性是在对象中存在时,可以使用两种方法:in
运算符和hasOwnProperty()
。
in
运算符仅仅会简单判断属性是否存在,而不会去读属性的值,这就能有效避免因为属性值为假值(0, "", false)时出现的歧义判断。
var obj = {
a: 0,
b: 10,
c: false
}
if('a' in obj){
console.log("属性a存在于对象obj中"); //属性a存在于对象obj中
}
if('b' in obj){
console.log("属性b存在于对象obj中"); //属性b存在于对象obj中
}
if('c' in obj){
console.log("属性c存在于对象obj中"); //属性c存在于对象obj中
}
而如果只是想检测实例对象的某个属性是否存在,可以使用hasOwnProperty()
。所有继承自Object
的对象都继承了这个方法。如果实例中存在该属性则返回true
,如果这个属性只存在于原型中,则返回false
。当然这个方法也是有兼容性,在IE8及更早版本的IE浏览器中,不存在这个方法,所以如果代码的生产环境可能包含IE8及以下时,需要先检测这个方法是否存在,检测方法为"hasOwnProperty" in object
。