数据类型的判断

136 阅读3分钟

这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战

数据类型的判断

数据类型分有基本数据类型和引用类型,基本数据类型有:string、number、boolean、undefined、null,引用类型有:object、array、function;js作为一门弱语言,在声明变量时,不需要先定义变量的数据类型,那么我们在日常开发中要怎么用代码将它们区分出来呢?这里牛逼的大佬就提供了一些方法

typeof

  • 我们可以使用typeof运算符来判断出变量的数据类型
// 字符串 string类型
typeof '12138' // String
// 数字 number类型
typeof 12138 // Number
// boolean类型
typeof false/true // Boolean
// undefined 类型
typeof undefined // Undefined
// null 类型
typeof null // Object
// 对象 object类型
typeof {} //Object
//数组 array类型
typeof [] // Object
// 函数 function类型
typeof function(){} // Object

从上面typeof对各个数据类型进行判断来看,所有的引用类型用这个方法判断得出的结果都是Object,很显然是不对的;而基本数据类型差不多都能正确的判断出来;但是,有一个坑,就是null,它判断出来居然也是Object类型。这也是js历史遗留下来的老bug了,为什么会出现这种情况呢?因为在JS的很早的版本中,是使用32位系统,为了性能考虑使用低位存储了变量的类型信息,000开头代表是对象,然而 null 表示为全零,所以将它错误的判断为object。虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来。

instanceof

  • instanceof 运算符用于检测构造函数的 prototype 属性是否在某个实例对象的原型链上
function Person() {}
function Person1() {}
let student = new Person();
student instanceof Person // true
student instanceof Person1 // false
  • 继承中判断实例是否属于它的父类
function Person() {}
function Student() {}
let people = new Person()
Student.prototype = people
let stu = new Student()
stu instanceof Person // true
  • 构造函数的prototype属性值也不是永恒不变的;比如,表达式o instanceof Foo 返回true,此时Foo.prototype还是在o的原型链上,那么我们来改变下Foo.prototypr = {},赋值之后,prototype属性值就发生了改变,o instanceof Foo 返回的就是false了。
function Foo(){}
let p = new Person()
Foo.prototype = {}
p instanceof Person // false
  • 还有一种方法也可以改变原表达式的值,就是改变实例对象的原型链;我们可以通过o.proto = {}来改变实例对象的原型链,这样的话,表达式返回的也是false。
function Foo(){}
let p = new Person()
p.__proto__ = {}
p instanceof Person // false
  • 但是,这个方法有个缺点,就是它只能判断一个对象是否存在于另一个对象的原型链上,不能判断基本数据类型。
  • 上面所说的两种判断方法都有一丢丢的限制,不能很愉快地判断所有类型,这就有点头大了;接下来就有一个很厉害的方法,无论是基本数据类型还是引用类型,它都能一一给你找出来;它就是Object.prototype.toString.call()。

Object.prototype.toString.call()

  • 每个对象都有一个toString()方法,当对象要表示为文本值或以期望字符串的方式引用对象时,该方法会自动调用;如果该方法没有被重写,则调用toString方法后返回的是'[Object xxx]'。
let o = new Object();
o.toString(); // returns [object Object]
  • 单单使用toString()方法来判断是不可靠的,对象可以Object.prototype.toString()通过定义一个 Symbol.toStringTag属性来改变行为从而来达到我们想要的结果。
// Boolean 类型
Object.prototype.toString.call(true);            // "[object Boolean]"
// Number 类型
Object.prototype.toString.call(1);               // "[object Boolean]"
// String 类型
Object.prototype.toString.call("");              // "[object String]"
// Array 类型
Object.prototype.toString.call([]);              // "[object Array]"
// Function 类型
Object.prototype.toString.call(function(){});    // "[object Function]"
// Date 类型
Object.prototype.toString.call(new Date());      // "[object Date]"