【面试直接答系列】JS的数据类型及检测

166 阅读3分钟

JS中的8种数据类型及区别

基本类型:存储在栈内存,被引用或拷贝时,会创建一个完全相等的变量

Number
String
Boolean
Symbol // ES6引入的数据类型,表示独一无二的值
null
undefined
BigInt // ES2020引入的新数据类型,它提供了一种方法来表示大于 2的53次方 - 1 的整数。这原本是Javascript中可以用Number表示的最大数字。BigInt可以表示任意大的整数

引用类型:Object( 包含:Array,RegExp,Date,Math,Function )

Lark20210108-154509.png

数据类型检测

typeof

console.log(typeof 1);               // number
console.log(typeof true);            // boolean
console.log(typeof 'mc');            // string
console.log(typeof Symbol)           // function
console.log(typeof BigInt)           // function
console.log(typeof function(){});    // function 
// 引用数据类型 Object,用 typeof 来判断的话,除了 function 会判断为 OK 以外,其余都是 'object',是无法判断出来的
console.log(typeof console.log());   // function
console.log(typeof []);              // object 
console.log(typeof {});              // object
console.log(typeof null);            // object  typeof null 为object是因为null的二进制全是0,所以也被判断为Object类型
console.log(typeof undefined);       // undefined// 能够快速区分出基本类型
// 不能区分出

原理:

  • typeof是操作符而不是函数,用来检测变量的类型

  • 数据在底层都表示为二进制,js中前三位(低位)代表数据类型

    • 000:对象
    • 110:布尔
    • 100:字符串
    • 010:浮点数
    • 1:整数

instanceof

语法: object instanceof constructor 等同于constructor.prototype.isPrototypeOf(object)

console.log(1 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false  
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true// instanceof代码实现
function instanceof(L, R) { //L是表达式左边,R是表达式右边
    const O = R.prototype;
    L = L.__proto__;
    while(true) {
        if (L === null)
            return false;
        if (L === O) // 这里重点:当 L 严格等于 O 时,返回 true 
            return true;
        L = L.__proto__;
    }
}
​
// 优点:能够区分Array、Object和Function,适合用于判断自定义的类实例对象
// 缺点:Number,Boolean,String基本数据类型不能判断

原理:

  • instanceof的机制是检测构造函数的prototype属性是否出现在某个实例对象的原型链上,是则返回true,否则false

结论:

  1. instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型;
  2. 而 typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了 function 类型以外,其他的也无法判断。

Object.prototype.toString

Object.prototype.toString({})       // "[object Object]"
Object.prototype.toString.call({})  // 同上结果,加上call也ok
Object.prototype.toString.call(1)    // "[object Number]"
Object.prototype.toString.call('1')  // "[object String]"
Object.prototype.toString.call(true)  // "[object Boolean]"
Object.prototype.toString.call(function(){})  // "[object Function]"
Object.prototype.toString.call(null)   //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g)    //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([])       //"[object Array]"
Object.prototype.toString.call(document)  //"[object HTMLDocument]"
Object.prototype.toString.call(window)   //"[object Window]"

实现一个全局通用的数据类型判断方法

function getType(obj) {
  let type = typeof obj
  if (type !== "object") {
    return type
  }
  return Object.prototype.toString.call(obj).replace(/^[object (\S+)]$/, '$1');  // 注意正则中间有个空格
}
​
/* 代码验证,需要注意大小写,哪些是typeof判断,哪些是toString判断?思考下 */
getType([])     // "Array" typeof []是object,因此toString返回
getType('123')  // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null)   // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined)   // "undefined" typeof 直接返回
getType()            // "undefined" typeof 直接返回
getType(function(){}) // "function" typeof能判断,因此首字母小写
getType(/123/g)      //"RegExp" toString返回
​

typeOf及instanceof原理