题目:使用 typeof bar === "object"
来确定 bar
是否是对象的潜在陷阱是什么?如何避免这个陷阱?
1:使用typeof
首先看下面的代码:
var carr=[];
var cobj={};
function cfun(){
console.log('cc');
}
console.log(typeof carr=='object'); //true
console.log(typeof cobj=='object'); //true
console.log(typeof cfun=='function'); //true
console.log(typeof null=='object'); //true
可以看到,typeof null也为‘object’,这一般不是我们所希望的。至于Array和Function是否希望被判断为object就要因情况而定了。
当希望排除掉null和函数是可以这样写:
var carr=[];
var cobj={};
function cfun(){
console.log('cc');
}
//判断是否是对象
function isObject(bar)
{
if((typeof bar==='object')&&(bar!==null))
return true;
else
return false;
}
console.log(isObject(carr)); //true
console.log(isObject(cobj)); //true
console.log(isObject(cfun)); //false
console.log(isObject(null)); //false
当希望排除掉null,函数,Array的时候可以这样写:
var carr=[];
var cobj={};
function cfun(){
console.log('cc');
}
//判断是否是对象
function isObject(bar)
{
if((typeof bar==='object')&&(bar!==null)&&(Object.prototype.toString.call(bar))!=='[object Array]')
return true;
else
return false;
}
console.log(isObject(carr)); //false
console.log(isObject(cobj)); //true
console.log(isObject(cfun)); //false
console.log(isObject(null)); //false
2:使用toString()
检测对象类型
可以通过toString()
来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString()
来检测,需要以 Function.prototype.call()
或者 Function.prototype.apply()
的形式来调用,传递要检查的对象作为第一个参数。结果显而易见了。
var carr=[];
var cobj={};
function cfun(){
console.log('cc');
}
var toString = Object.prototype.toString;
console.log(toString.call(new Date)); // [object Date]
console.log(toString.call(new String)); // [object String]
console.log(toString.call(Math)); // [object Math]
console.log(toString.call(undefined)); // [object Undefined]
console.log(toString.call(null)); // [object Null]
console.log(toString.call(carr)); // [object Array]
console.log(toString.call(cobj)); // [object Object]
console.log(toString.call(cfun)); // [object Function]
3:更全面的检测对象的方式(jQuery中的方法)
当然如果你觉得上述方法仍然不够全面,那么我们来看看jQuery中是如何判断对象类型的。jQuery全面考虑到了各种情况及浏览器版本的兼容性。
jQuery(版本1.11.1)中部分代码:
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
jQuery.extend({
//检测isPlainObject方法被用来检测是否为“朴素对象”
//不是DOM,原型链上直接继承Object.prototype的对象,称为“朴素对象”
isPlainObject: function( obj ) {
var key;
//排除非object类型,然后是DOM对象,window对象
if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
return false;
}
try {
// Not own constructor property must be Object
if ( obj.constructor &&
!hasOwn.call(obj, "constructor") &&
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
return false;
}
} catch ( e ) {
// IE8,9 Will throw exceptions on certain host objects #9897
return false;
}
//兼容老版本浏览器
// Support: IE<9
// Handle iteration over inherited properties before own properties.
if ( support.ownLast ) {
for ( key in obj ) {
return hasOwn.call( obj, key );
}
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
for ( key in obj ) {}
return key === undefined || hasOwn.call( obj, key );
},
type: function( obj ) {
if ( obj == null ) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call(obj) ] || "object" :
typeof obj;
},
});
// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
});