类型
目前,Javascript 中的常用的数据类型如下,其中,Object为复合类型,其余都是基础类型
Number(数字)String(字符串)Boolean(布尔)Null(空)Undefined(未定义)Symbol(唯一的值)Object(对象)
复合类型的代表是 Object(对象),Object 又有三个子类型:Object (纯对象),Function(函数类型),Array(数组类型)
此外,值得注意的是 Javascript 还提供了一种新的基本类型 Bigint ,它用来表示任意大小的整数,目前的情况是各大浏览器对于 Bigint的支持度不一样,还未普及,所以这里不做深究
类型判断
typeof
typeof 是一个一元操作符,后面跟一个 Javascript 变量,返回这个变量的类型字符串
function ty(value){
console.log(typeof value)
}
ty(120) // number
ty('Hello') // string
ty([1,2,3]) // object
ty(true) // boolean
ty(undefined) // undefined
ty(Symbol()) // symbol
ty({msg: 'Hello World'}) // obejct
ty(ty) // function
ty(null) // object
复制上面的代码,打开浏览器控制台就能查看 typeof 检测类型的结果;你肯定注意到了这个 null 的类型居然是 object!其实这是一个历史遗留 bug
null的类型是object,这是由于历史原因造成的。1995年的 JavaScript 语言第一版,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),没考虑null,只把它当作object的一种特殊值。后来null独立出来,作为一种单独的数据类型,为了兼容以前的代码,typeof null返回object就没法改变了
摘自 ——《Javascript标准参考教程》阮一峰
从上面的代码可以发现, typeof 只适合用于简单地判断基本类型和对象类型,它并不能判断出数组
instanceof
instance 是一个二元操作符,用于比较一个对象是否是另一个构造函数的实例,它通过比较两个对象的 prototype ,返回一个布尔值
instanceof 的用法就是在左边放置一个对象实例,右边放置一个构造函数(代表对象的确切类型)
function it(a, b){
console.log(a instanceof b)
}
function Person(){}
Person.prototype.msg = 'Hello'
const boy = new Person()
const girl = new Person()
// boy和girl 是 构造函数 Person 的实例化对象,所以 instanceof 操作符返回 true
it(boy, Person) // true
it(girl, Person) // true
// 用于判断一个对象是否是数组
const arr = [1,2,3]
it(arr, Array) // true
it(arr, Object) // true
上面的代码暴露出了 instanceof 的一个问题,因为通过 instanceof 来判断的话,arr 既是 Array 类型的又是 Object 类型的,所以 instanceof 不能用来判断一个数据是不是 Array 类型
ES6 提供了一个新方法 Array.isArray() 用来判断一个对象是不是数组
toString()
toString 是 Object 原型上的方法,所有的对象的原型对象,最终都会指向 Object,所以每个对象都会有一个 toString 方法。Object.toString()返回一个字符串,其格式为[object xxx] ,其中 xxx 就是对象的类型
function ts(value) {
console.log(Object.prototype.toString.call(value))
}
function Man(){}
Man.prototype.msg = 'Hello'
const jack = new Man()
ts('Hello') // [object,String]
ts(123) // [object,Number]
ts([1, 2, 3]) // [object,Array]
ts(function () { }) // [object,Function]
ts({}) // [object,Object]
ts(Symbol()) // [object,Symbol]
ts(null) // [object,Null]
ts(undefined) // [object,Undefined]
ts(jack) // [object,Object]
toString() 方法很强大,可以看到几乎所有的类型都能被准确判断出来,但有一个问题,那就是对象上的 toString 是不稳定的,它可以被改写,所以,如果对象的 toString 方法被改写了,那么使用 toString 来判断的数据类型也没有了意义
总结
本文一共介绍了3种判断数据类型的方法:typeof、instanceof、toString,它们各自拥有优缺点,其实还有一种方法可以判断数据类型,那就是使用 constructor 属性,只是本人觉得的此方法非常不靠谱,所以就没有提。
聪明的你可能已经发现,Javascript 这门语言居然没有一个通用的、稳定的、可靠的判断数据类型的方法!
但是这并不妨碍我们通过合理的运用上面的三种方法来做出相对准确的数据类型判断,我总结出下面规则:
- 判断基础类型和函数类型用 typeof
- 判断复合类型用 Object.prototype.toString.call()
- 判断自定义的对象类型用 instanceof
- 判断数组就用Array.isArray()
类型转换
强制类型转换
类型转换遵守以下规则(图片来自于 ConardLi):
parseInt
parseInt(string, radix) 用于解析一个字符串并返回指定基数的十进制整数, radix 是2-36之间的整数,表示被解析字符串的基数。例如,parseInt('456', 8)表示 456 是一个 8 进制数,将其转为 10 进制数。parseInt只会解析并转换字符串的首段表示数字的字符,如果字符串的第一个字符不是数字,那么 parseInt会返回 NaN
parseInt('Hahh',10) // NaN
parseInt('015',10) // 15
parseInt('-15',10) // -15
parseInt('3*56+7',10) // 3
parseInt(' 7 3',10) // 7
使用 parseInt必须始终指定字符串的基数
parseFloat
parseFloat(string) 用于解析一个字符串,并返回一个浮点数。它返回 10 进制浮点数,所以不需要指定基数
parseFloat('3.14'); // 3.14
parseFloat('Hello'); // NaN
parseFloat('3.14+5.78'); // 3.14
parseFloat(' 7.63+5.78'); // 7.63
参考资料: