数据类型及其检测

84 阅读3分钟

基本数据类型

  • number => NaN/Infinity
  • string => 单引号/双引号/反引号
  • boolean => true/false
  • null => 空对象指针
  • undefined => 未定义
  • bigint => 超过最大安全值使用
  • symbol => 创建唯一值

引用数据类型

  • object
    • function
    • 数组对象 (Set属于这里)
    • 普通对象 (Map属于这里)
    • 正则对象
    • Math数学对象
    • 日期对象
    • prototype原型对象
    • ...

数据类型检测

  • typeof 检测数据类型的逻辑运算符
  • instanceof - 检测是否为某个类的实例
  • constructor - 检测构造 函数
  • Object.prototype.toString.call - 检测数据类型

typeof

typeof [value] 返回当前值的数据类型

  • 返回的结果都是字符串
  • 局限性:
    • typeof null // "object"
    • typeof 不能细分对象类型

typeof null为啥是"object"?

这是遗留的一个bug。不同的对象在底层原理的存储是用二进制表示的,在js中,如果二进制的前三位都为0的话,系统会判定是object类型。null的存储二进制是000,也是前三位,所以系统判定null为Object类型。

  • 000:对象类型
  • 1:整型
  • 010:浮点数
  • 100:字符串
  • 110:布尔类型
typeof 123; // "number"
typeof 'abc'; // "string"
typeof true; // "boolean"
typeof null; // "object"
typeof {}; // "object"
typeof undefined; // "undefined"
typeof function() {}; // "function"
typeof []; // "object"
typeof Symbol('1'); // "symbol"
typeof BigInt('1'); // "bigint"
typeof NaN; // "number"
typeof Infinity; // "number"
typeof -Infinity; // "number"

其中数组,对象,null都判定为'object',其他都正确。

let a = typeof typeof typeof [12, 23];
console.log(a); // "string"
// typeof typeof "object"
// typeof "string"
  • 'number'

Number.MAX_SAFE_INTEGER,js中最大的安全数,超过这个值的,要用bigint处理。(在一个数值后面加n就是bigint类型) // 90071992547409122222n

let res = parseFloat('left: 200px');
if (res === 200) {
    alert(200);
} else if (res === NaN) {
    alert(NaN);
} else if (typeof res === 'number') {
    alert('number');
} else {
    alert('Invalid Number');
}

// parseFloat检测里面的字符串(不是字符串就要先转换为字符串类型),从左侧第一个字符开始找有效数字,直到非有效数字为止,返回找到的有效数字。如果一个都没有,那就返回NaN。
// res是NaN
// NaN跟谁都不相等,但NaN属于number类型,因此alert('number');
// alert的内容必须转换为字符串
  • symbol

let val = Symbol('00'); console.log(val == val); // true

console.log(Symbol('aa') == Symbol('aa')); // false

instanceof

instanceof可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型【prototype属性】。

2 instanceof Number; // false
true instanceof Boolean; // false
'str' instanceof String; // false

[] instanceof Array; // true
function() {} instanceof Function; // true
{} instanceof Object; // true

由此可知,instanceof只能正确判断引用数据类型,而不能判断基本数据类型。

constructor

(2).constructor === Number; // true
(true).constructor === Boolean; // true
('str').constructor === String; // true
(\[]).contructor === Array; // true
(function() {}).contructor === Function; // true
({}).contructor === Object; // true

constructor有两个作用:

  • 判断数据类型
  • 对象实例通过contructor对象访问它的构造函数。

需要注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了;

Object.prototype.toString.call()

同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,是因为:

toString是Object的原型方法,而Arrayfunction等类型作为Object的实例,都重写了toString方法。

不同对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法。