JS数据类型判断

209 阅读3分钟

你好,我是南一。这是我在准备面试八股文的笔记,如果有发现错误或者可完善的地方,还请指正,万分感谢🌹

数据类型判断

1.typeof 操作符

number

//输出 number
console.log(typeof 1);                
console.log(typeof NaN);  		 // 尽管他是Not-A-Number    
console.log(typeof Number('1')); // Number 会尝试把参数解析成数值
console.log(typeof Infinity);	 // 无限大也是number

console.log(typeof 42n);		 // 这个输出bigint

string

//输出 string
console.log(typeof 'mc');
console.log(typeof '');
console.log(typeof `adadad`); // 模板字符串
console.log(typeof (typeof 1)); // typeof 操作符 返回字符串
console.log(typeof String(1)); // String 将任意值转换为字符串,比 toString 更安全

boolean

//输出 boolean
console.log(typeof true);              
console.log(typeof Boolean(1)); // Boolean(1)是true  Boolean(0)是false
console.log(typeof !!(1));// 两次调用 ! (逻辑非) 操作符相当于 Boolean() true

undefined

声明但未初始化未声明 typeof输出都是"undefined",但直接打印未声明变量是会报错的

console.log(typeof undefined);          // undefined
console.log(typeof console.log());      // undefined

function

console.log(typeof Symbol)              // function
console.log(typeof function () { });    // function
console.log(typeof new Function())      // function

object

// object
console.log(typeof []);                 
console.log(typeof {});              
console.log(typeof null);              
console.log(typeof new Date()); // 除 Function 外的所有构造函数的类型都是 'object'
console.log(typeof /regex/);

symbol

//symbol
console.log(typeof Symbol());          
console.log(typeof Symbol('foo'));
console.log(typeof Symbol.iterator);

优点:能够快速区分基本数据类型

缺点:不能将Object、Array和Null区分,都返回object

typeof 实现原理:

js 在底层是怎么存储数据的类型信息呢?

其实,js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息

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

但是,对于 undefinednull 来说,这两个值的信息存储是有点特殊的。

null:所有机器码均为0

undefined:用 −2^30 整数来表示

所以,typeof 在判断 null 的时候就出现问题了,由于 null 的所有机器码均为0,因此直接被当做了对象来看待。

2.instanceof 运算符

instanceof运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

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
console.log(null instanceof Object);                    // false

优点:能够区分Array、Object、Function,适用于判断自定义的类实例对象

缺点:Nunmer、boolean、String基本数据类型不能判断

instanceof 原理模拟实现

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

其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。

3.Object.prototype.toString.call()

var toString = Object.prototype.toString;
console.log(toString.call(1));                      //[object Number]
console.log(toString.call(true));                   //[object Boolean]
console.log(toString.call('mc'));                   //[object String]
console.log(toString.call([]));                     //[object Array]
console.log(toString.call({}));                     //[object Object]
console.log(toString.call(function () { }));        //[object Function]
console.log(toString.call(undefined));              //[object Undefined]
console.log(toString.call(null));                   //[object Null]
console.log(toString.call(Symbol()));               //[object Symbol]

优点:精准判断数据类型

缺点:写法繁琐不容易记,推荐进行封装后使用

简单封装

let typeUtil = {};
let types = ['String', 'Array', 'Number', 'Object', 'Undefined', 'Null', 'Boolean', 'Function', 'Symbol'];
types.forEach(type => {
  typeUtil['is' + type] = function (obj) {
    return Object.prototype.toString.call(obj) === `[object ${type}]`;
  }
})
console.log(typeUtil);
//{
//  isString: [Function (anonymous)],
//  isArray: [Function (anonymous)],
//  isNumber: [Function (anonymous)],
//  isObject: [Function (anonymous)],
//  isUndefined: [Function (anonymous)],
//  isNull: [Function (anonymous)],
//  isBoolean: [Function (anonymous)],
//  isFunction: [Function (anonymous)],
//  isSymbol: [Function (anonymous)]
//}

由于String基本包装类型的存在,在必要的时候JS引擎会把字符串字面量转换成一个String对象,从而可以执行访问属性和方法的操作

Object类型的每个实例都有toString方法,返回对象的字符串表示,所以每个实例化的对象都可以调用toString方法。

参考文章

MDN

连八股文都不懂还指望在前端混下去么