JavaScript 用typeof来判断是否是对象的弊端

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cc_fys/article/details/81180126

题目:使用 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]
扫描二维码关注公众号,回复: 3019051 查看本文章

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();
});

猜你喜欢

转载自blog.csdn.net/cc_fys/article/details/81180126