在找工作过程中,很多人都会被问到类似这样的问题,相信很多人都会脱口而出用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__
}
}
复制代码
总结
- typeof在判断基本数据类型时是没问题的。
- 如果需要判断一个对象的具体类型,可以使用instanceof。但是instanceof不够灵活,也可能判断不准确。
- 要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call和Object.prototype.toString.apply。