在找工作过程中,很多人都会被问到类似这样的问题,相信很多人都会脱口而出用typeof。下面我们来分析下,如何准确回答此类问题。

1、typeof

typeof一般被用来判断一个变量的类型,我们可以利用它判断number,string, object,bolean,function,undefined,symbol这7中类型,也就是javascript中的数据类型。这种判断能帮我们搞定一些问题,例如在判断一些非object类型变量时,它能告诉我们是哪一种类型。但判断Object类型的变量时,只能告诉我们是Object类型,而不能具体到哪一种Object。

let s = new Number(4);
typeof s === 'object'; // true
instanceof s ===  Number // true
let arr = new Array(1,2,3);
typeof arr;  "object"
复制代码

当然typeof除了判断Object类型不准确外,还有一种情况下会出现异常:Null,由于Null的在js底层存储变量的机器码均为0,而对象Object在底层存储变量的机器码也均为0,因此,typeof在判断变量类型时把Null被当做对象来看。综上所述,我们在利用typeof来判断变量类型时,应该避免对Null的判断。

2、Object.prototype.toString

var a = [1, 2, 3, 4, 5];
var b = function () { }
var c = { 'age': 18, 'sex': '男' }
console.log(typeof a, typeof b, typeof c); // object function object
console.log(Object.prototype.toString.apply(a), Object.prototype.toString.call(a), Object.prototype.toString.apply(a)); //  [object Array] [object Array] [object Array]
console.log(Object.prototype.toString.apply(b), Object.prototype.toString.call(b), Object.prototype.toString.apply(b)); // [object Function] [object Function] [object Function]
console.log(Object.prototype.toString.apply(c), Object.prototype.toString.call(c), Object.prototype.toString.apply(c)); // [object Object] [object Object] [object Object]
复制代码

3、instanceof

前面我们提到利用instanceof来判断对象的具体类型。与 typeof 方法不同的是,instanceof 方法要求开发者明确地确认对象为某特定类型。如:

var oStringObject = new String("hello world"); 
console.log(oStringObject instanceof String);   // 输出 "true"
复制代码

尽管不像typeof灵活,但在判断Object对象具体类型的情况下,instanceof派上用场。他用于检测左边对象是不是右边对象的实例。 其实instanceof的实现原理就是只要右边变量的prototype在左边变量的原型链上即可。如果在,则返回true;否则返回false。特别说明一点,要避免使用instance检测Null变量,因为会报异常,这是javasctipt底层的bug。

function new_instance_of(leftVaule, rightVaule) { 
    let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
    leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
    while (true) {
    	if (leftVaule === null) {
            return false;	
        }
        if (leftVaule === rightProto) {
            return true;	
        } 
        leftVaule = leftVaule.__proto__ 
    }
}
复制代码


总结

  1. typeof在判断基本数据类型时是没问题的。
  2. 如果需要判断一个对象的具体类型,可以使用instanceof。但是instanceof不够灵活,也可能判断不准确。
  3. 要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call和Object.prototype.toString.apply。