跳到主要内容

数据类型

JavaScript数据类型

最新的 ECMAScript 标准定义了 8 种数据类型

七种基本数据类型:

  • 数字(Number),整数或浮点数,例如: 42 或者 3.14159。
  • 字符串(String),字符串是一串表示文本值的字符序列,例如:"Howdy" 。
  • 布尔值(Boolean),有 2 个值分别是:true 和 false.
  • 代表(Symbol)( 在 ECMAScript 6 中新添加的类型).。一种实例是唯一且不可改变的数据类型。
  • 任意精度的整数 (BigInt) ,可以安全地存储和操作大整数,甚至可以超过数字的安全整数限制。
  • undefined ,和 null 一样是一个特殊的关键字,undefined 表示变量未赋值时的属性。
  • null , 一个表明 null 值的特殊关键字。 JavaScript 是大小写敏感的,因此 null 与 Null、NULL或变体完全不同。

以及对象(Object)。

判断数据类型

  • typeoftypeof target,返回一个表示操作值的类型全小写字符串
  • instanceof:target instanceof Fn,判断一个对象是否为某一个构造函数的实例(复杂数据类型)
  • constructor:target.constructor === Fn,判断一个对象是否为某一个构造函数的实例(除null和undefined=>自动将基本数据类型的值转为包装对象实例)
  • Object.prototype.toString:Object.prototype.toString.call(target),返回对象的类型字符串,可以准确判断所有数据类型(调用Object的原型方法,获取对象的class属性)

typeof示例如下:

console.log(typeof 123) // 'number'
console.log(typeof '123') // 'string'
console.log(typeof true) // 'boolean'
console.log(typeof Symbol(123)) // 'symbol'
console.log(typeof BigInt(123)) // 'bigint'
console.log(typeof undefined) // 'undefined'
console.log(typeof null) // 'object'
console.log(typeof []) // 'object'
console.log(typeof {}) // 'object'
console.log(typeof function(){}) // 'function'
console.log(typeof new Date()) // 'object'
console.log(typeof /\d/g) // 'object'
console.log(typeof new Error()) // 'object'

typeof可以准确判断除null之外的所有基本数据类型以及Function,对于 null 及其他引用数据类型都返回 object


instanceof示例如下:

console.log(123 instanceof Number) // false
console.log('123' instanceof String) // false
console.log(true instanceof Boolean) // false
console.log(Symbol(123) instanceof Symbol) // false
console.log(10n instanceof BigInt) // false
console.log(undefined instanceof undefined) // TypeError: Right-hand side of 'instanceof' is not an object
console.log(null instanceof null) // TypeError: Right-hand side of 'instanceof' is not an object
console.log([] instanceof Array) // true
console.log({} instanceof Object) // true
console.log(function(){} instanceof Function) // true
console.log(new Date() instanceof Date) // true
console.log(/\d/g instanceof RegExp) // true
console.log(new Error() instanceof Error) // true
  • instanceof用来判断一个对象是否为某一个构造函数的实例,这些基本数据类型不是通过let str = new String('hello');console.log(str instanceof String);//true形式创建的, 所以都是false,因此instanceof一般不能判断基本数据类型,因为判断null和undefined不是对象没有.prototype,所以会报错

主要的实现原理就是右边变量的prototype在左边变量的原型链上即可

function Test(){
this.title = 'test title'
}
const hello = new Test()
// Test.prototype 构造函数的原型对象
// 对象都会有一个属性__proto__指向构造函数的prototype原型对象
console.log(hello.__proto__ === Test.prototype)
// 判断
console.log(hello instanceof Test)

constructor示例如下:

console.log((123).constructor === Number) // true
console.log('123'.constructor === String) // true
console.log(true.constructor === Boolean) // true
console.log(Symbol(123).constructor === Symbol) // true
console.log(BigInt(123).constructor === BigInt) // true
// console.log(undefined.constructor === undefined)// TypeError: Cannot read properties of undefined (reading 'constructor')
// console.log(null.constructor === null)// TypeError: Cannot read properties of null (reading 'constructor')
console.log([].constructor === Array) // true
console.log({}.constructor === Object) // true
console.log(function () { }.constructor === Function) // true
console.log(new Date().constructor === Date) // true
console.log(/\d/g.constructor === RegExp) // true
console.log(new Error().constructor === Error) // true

constructor用于判断操作值是否是指定构造函数的实例,可以判断除null和undefined外的所有数据类型【null 和 undefined作为 JavaScript 运行环境创建时就存在的基本数据类型,不存在 constructor 属性】

function Test(){
this.title = 'test title'
}
const hello = new Test()
// Test.prototype 构造函数的原型对象
// 1.对象都会有一个属性__proto__指向构造函数的prototype原型对象
console.log(hello.__proto__ === Test.prototype)
// 2.构造函数的 prototype 对象默认都有一个 constructor 属性,指向 prototype 对象所在函数。
console.log(Test.prototype.constructor === Test)
// 判断=>等价
console.log(hello.__proto__.constructor === Test)
console.log(hello.constructor === Test)

基本数据类型为什么会有 constructor 属性呢?

基本数据类型获取 constructor 属性的时候,JavaScript 自动将基本数据类型的值转为包装对象实例,并在使用后立刻销毁实例。

constructor属性可以被修改,所以结果值不一定准确。


Object.prototype.toString.call()示例如下:

// '[object Number]'
console.log(Object.prototype.toString.call(123))
// '[object String]'
console.log(Object.prototype.toString.call('123'))
// '[object Boolean]'
console.log(Object.prototype.toString.call(true))
// '[object Symbol]'
console.log(Object.prototype.toString.call(Symbol(123)))
// '[object BigInt]'
console.log(Object.prototype.toString.call(BigInt(123)))
// '[object Undefined]'
console.log(Object.prototype.toString.call(undefined))
// '[object Null]'
console.log(Object.prototype.toString.call(null))
// '[object Array]'
console.log(Object.prototype.toString.call([]))
// '[object Object]'
console.log(Object.prototype.toString.call({}))
// '[object Function]'
console.log(Object.prototype.toString.call(function(){}))
// '[object Date]'
console.log(Object.prototype.toString.call(new Date()))
// '[object RegExp]'
console.log(Object.prototype.toString.call(/\d/g))
// '[object Error]'
console.log(Object.prototype.toString.call(new Error()))
typeofinstanceofconstructorObject.prototype.toString
Number
String
Boolean
Symbol
BigInt
undefined
null
Array
Object
Function
Date
RegExp
Error

Object.prototype.toString.call()准确判断数据类型原因:

Object.prototype.toString()是Object的原型方法,获取对象的class属性

在Object.prototype.toString()中,toString()的入参不管是什么,它的调用者永远都是Object.prototype,在不加call()情况下,结果永远都是'[object Object]'

对于Object对象,调用Object.prototype.toString()就能返回'[object Object]' 。而对于其他对象,则需要通过call/apply来调用才能返回正确的类型信息。

使用.call()让Object.prototype.toString这个方法指向传入的数据

不直接使用数据本身去调用toString(),是因为每个数据类都重新了toString方法

// 123
console.log((123).toString())
// 123
console.log('123'.toString())
// true
console.log(true.toString())
// Symbol(123)
console.log(Symbol(123).toString())
// 123
console.log(BigInt(123).toString())
// TypeError: Cannot read properties of undefined (reading 'toString()')
// console.log(undefined.toString())
// TypeError: Cannot read properties of null (reading 'toString()')
// console.log(null.toString())
// 1,2
console.log([1,2].toString())
// [object Object]
console.log({a:1}.toString())
// function(){}
console.log(function(){}.toString())
// Thu Aug 04 2022 22:29:08 GMT+0800 (中国标准时间)
console.log(new Date().toString())
// /\d/g
console.log(/\d/g.toString())
// Error
console.log(new Error().toString())

封装Object.prototype.toString()

export const typeOf = <T>(obj: T): string | undefined => {
const toString = Object.prototype.toString
const map = {
'[object String]': 'string',
'[object Number]': 'number',
'[object Boolean]': 'boolean',
'[object Null]': 'null',
'[object Undefined]': 'undefined',
'[object BigInt]': 'bigInt',
'[object Symbol]': 'symbol',
'[object Array]': 'array',
'[object Object]': 'object',
'[object Function]': 'function',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Error]': 'error',
}
return map[toString.call(obj)]
}
console.log(typeOf('a'));
console.log(typeOf(1));
console.log(typeOf(false));
console.log(typeOf(null));
console.log(typeOf(undefined));
console.log(typeOf(BigInt(10)));
console.log(typeOf(Symbol(1)));
console.log(typeOf([]));
console.log(typeOf({}));
console.log(typeOf(() => { }));
console.log(typeOf(new Date()));
console.log(typeOf(new RegExp('')));
console.log(typeOf(new Error()));