typeof
基础用法
typeof 1; // 'number'
typeof NaN; // 'number'
typeof '1'; // 'string'
typeof Symbol('test'); // 'symbol'
typeof true; // 'boolean'
typeof undefined: // 'undefined'
typeof null; // 'object'
typeof []; // 'object'
typeof {}; // 'object'
typeof console.log; // 'function'
typeof typeof null // 'object'
总结:typeof判断基础数据类型时,除了null,其他返回的值都是数据对应的类型。在判断引用数据类型的时候,除了函数,其他返回的值都是object。值得注意是,typeof 返回值的类型是string。
原理浅析
要想弄明白为什么typeof判断null为object,需要从js底层如何存储变量类型来说,虽然说,这是JS设计的一个bug。
在JS最初的实现中,值是有一个表示类型的标签和实际数据值表示的。对象的类型标签是0。由于null代表的是空指针(大多数平台下值为0x00),因此null的类型标签是0,typeof null也因此返回object。
js在底层存储变量的时候,会在变量的机器码的低位1-3存储其类型信息:
- 1 整数
- 110 布尔
- 100 字符串
- 010 浮点数
- 000 对象
但是对于undefined和null来说,这两个值的信息存储有点特殊的:
null所有的机器码均为0undefined用−2^30 整数来表示表示
所以在用typeof来判断变量类型的时候,我们需要注意,最好是用typeof来判断基本数据类型(包括symbol),避免对null的判断。
instanceof
instanceof可以正确判断对象的类型,是因为内部机制是通过判断对象的原型链中是不是能找到类型的prototype。
基础用法
function A() {}
function B() {}
var a = new A();
a instanceof A; // true
手写instanceof
function myInstanceof(left, right){
let prototype = right.prototype;
left = left.__proto__;
while(true) {
if(left === null || left === undefined) {
return false;
}
if(prototype === left) {
return true;
}
left = left.__proto__
}
}
实现分析:
- 获取类型的原型
- 获取对象的原型
- 然后一直循环判断队形的原型是否等于类型的原型,直到对象原型为null,因为原型链的终点是null
es6的 isArray
Array.isArray 只是用来判断是否为数组
Array.isArray([]); // true
Array.isArray({}); // false
Object.prototype.toString;
因为不同的数据类型中内置的toString方法是有区别的,所以我们借助Object原型上的toString来做统一处理
Object.prototype.toString.call(''); // '[object String]'
Object.prototype.toString.call(1); // '[object Number]'
Object.prototype.toString.call(true); // '[object Boolean]'
Object.prototype.toString.call(Symbol('test')); // '[object Symbol]'
Object.prototype.toString.call(null); // '[object Null]'
Object.prototype.toString.call(undefined); // '[object Undefined]'
Object.prototype.toString.call({}); // '[object Object]'
Object.prototype.toString.call([]); // '[object Array]'
Object.prototype.toString.call(console.log); // '[object Function]'
Object.prototype.toString.call(new Date()); // '[object Date]'
(function() {
Object.prototype,toString.call(arguments); // '[object Arguments]'
})();
封装一个获取变量类型的方法
function getType(varibale) {
const typeStr = Object.prototype.toString.call(varibale);
return typeStr.match(/\s+(\w+)/)[1];
}
getType({}); // Object
getType(''); // String