Day4 - 判断数据类型的方式有哪些?
su37josephxia opened this issue · 17 comments
考察:数据类型的判断分为基本类型和引用类型
对于基本类型的数据,我们用 typeof
,判断 undefined
,Number
, Boolean
, String
,
对于 null
,由于 typeof null === 'object'
,所以我们要对 null
单独做判断,
另外 typeof
也可以检测一个数据是不是 function
。
对于引用类型 Object
,我们用 Object.prototype.toString
,他返回的字符串表示数据的具体类型,我们用它可以判断出 regex
, Object
, arguments
等引用类型。
另外,判断一个对象是不是某个具体类型,我们用 instanceOf
。
常用的判断数据类型的方式有
typeof
instanceof
constructor
typeof
typeof
用以获取一个变量或者表达式的类型-一般用于判断值类型
问题:
arr, json, nul, date, reg, error
全部被识别为object
。而number, string, boolean, function, undefined
可以被识别
instanceof
instanceof
运算符是用来判断一个对象是否在其原型链原型构造函数的属性,所以在比较对象(引用类型)时才有意义。
问题:
instanceof
不能判断值类型,但是引用类型可以,另外arr
和obj
在instanceof Object
的时候的值都是true
constructor
constructor
本来是原型对象上的属性,指向构造函数。但是根据实例对象寻找属性的顺序,若实例对象上没有实例属性或方法时,就去原型链上寻找,因此,实例对象也是能使用constructor
属性的
问题:undefined和null没有constructor属性,所以判断时代码可能会报错。由于constructor属性是可以变更的,也会导致检测出的结果不正确
其他方法
Object.prototype.toString
Object.prototype.toString.call(num), // '[object Number]'
Object.prototype.toString.call(str), // '[object String]'
Object.prototype.toString.call(bool), // '[object Boolean]'
Object.prototype.toString.call(arr), // '[object Array]'
Object.prototype.toString.call(obj), // '[object Object]'
Object.prototype.toString.call(func), // '[object Function]'
Object.prototype.toString.call(und), // '[object Undefined]'
Object.prototype.toString.call(nul), // '[object Null]'
Object.prototype.toString.call(date), // '[object Date]'
Object.prototype.toString.call(reg), // '[object RegExp]'
Object.prototype.toString.call(error) // '[object Error]'
判断数据类型的方式有
typeof
instanceof
constructor
Object.prototype.toString.call()
isArray()
typeof
只适用于判断基本数据类型,[] / {} / null / Function
都会被判断为 object 类型
instanceof
用于判断一个对象的原型对象是否在其构造函数的原型链上,只适合判断引用类型
constructor
适用于判断 null / undefined
之外的数据类型,基本数据类型会被自动装箱
Object.prototype.toString.call()
适用于所有数据类型,判断基本数据类型时会被自动装箱
isArray()
isArray( ) 是 ES6 用于判断数组类型的函数
数据类型判断方式有3种
- typeof
- instanceof
- Object.prototype.toString.call(xxx)
说明
-
typeof
- JS设计bug,typeof null 的结果是 object
- 有暂时性死区的问题,所以不是100%安全
-
instanceof
- 右边变量的 prototype 在左边的原型链上
- 原型链可以修改,也不一定安全
-
Object.prototype.toString.call(xxx)
- 返回的是[[class]] 私有属性,是 ECMA 标准,类型判断很安全
答
常见的数据类型判断
typeof
isArray()
Object.prototype.toString.call()
- 粗略的判断数据类型,一般用typeof,可以得到number boolean string function object
- 细致的判断根据需求选用方法,比如判断数组用isArray 判断,判断是否是对象用Object.prototype.toString.call()
- 判断空对象 Object.keys(object).length === 0
补充
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
isNaN 允算法,判断参数是否是NaN
常见的类型判断方式
- typeof
- instanceof
- Object.propertype.toString.call(xxx);
说明
typeof可以检测基本数据类型的类型,对于js中的一些特殊情况检测的精确度不有些问题,object、array都会被检测为对象类型,null的类型也是object
instcanceof:
可以判断对象在不在对象的原型链中
Object.prototype.toString.call(xxx)返回的是对象的[[Class]],是标准规范内的描述,相对比较安全。
判断数据类型的方式主要有 typeof 、instanceof 、Object.prototype.toString。
typeof除了 数组和对象和null之外,都能准确区分出来。instanceof检测是否在隐式原型链上,分不清function和object和数组,但是能区分出null。Object.prototype.toString 是最稳定的方法,能够拿到构造函数的名字。
1.typeof 可以判断js中除了null之外的基本数据类型和function ,typeof 对引用类型的数据还有null都会返回object
2.instanceof 可以检测引用类型数据的原型链中是否含有目标对象
3.Object.prototype.toString 方法返回对象的Class,是相对来说比较理想的检测方式
- typeof
- instanceof
- constructor
- Object.prototype.toString.call()
-
typeof
typeof data 返回的结果是 data 类型的字符串,字符串全部是小写的,但是
- 对于基本类型,除 null 以外,均可以返回正确的结果。
- 对于引用类型,除 function 以外,一律返回 object 类型。
- 对于 null ,返回 object 类型。
- 对于 function 返回 function 类型。
-
instanceof
instanceof 检测的是原型链上是否存在其原型,如果存在就返回true,否侧返回false
-
constructor
constructor指向其的构造函数,在创建一个函数的时候会有一个prototype原型,原型上有个constructor属性 指向其构造函数
-
Object.prototype.toString.call()
通过这个方法返回一个 '[object xxxx]'的字符串,可以xxx代表其类型
常用的有三种方式 typeof
instanceof
Object.prototype.toString.call()
- typeof 返回表示数据类型的字符串,(数字,布尔值,字符串,undefined,function, object),typeof判断
null
和引用类型(除了function),都返回object
- instanceof 返回布尔值,判断一个对象是否另一个对象的实例,一般用来判断引用类型,因为只要在原型链上找到就返回true,
[] instanceof Array
,[] instanceof Object
返回都是true依然不是很精准 - Object.prototype.toString.call() 可以得到对象的构造函数名,格式为[object Xxx]是最精确的
结论
- typeof
- instanceof
- constructor
- Object.prototype.toString.call()
其他 Array.isArray Number.isInteger() Number.isFinite() 等等
引申
- typeof 可以判断function的类型;在判断除Object类型的对象时比较方便 但是会将数组 null判断为对象
- instanceof 检测其左侧是否在右侧原型链上存在其原型,如果存在就返回true,否侧返回false,但是在判断数组时依旧不是很精准
- constructor 主要是利用原型上的prototype.constructor指向实例的构造函数来进行判断的 当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object。null, undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断
- Object.prototype.toString.call() 该方法基本上能判断所有的数据类型(自定义数据类型除外) 推荐使用
判断数据类型的方式有三种
- typeof
- instanceof
- toString;
说明
typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型;
对于基本类型,除 null 以外,均可以返回正确的结果;
对于引用类型,除 function 以外,一律返回 object 类型;
对于 null ,返回 object 类型;
对于 function 返回 function 类型;
instanceof 判断某个实例是不是属于原型;
instanceof 能够判断出 [ ] 是 Array 的实例,但它认为 [ ] 也是 Object 的实例;
因此,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型
toString() 是 Object 的原型方法,其格式为 [object XXX] ,其中 XXX 就是对象的类型。
js中数据类型分为两大类:基本类型(简单类型),引用类型(对象)
- 基本类型 Undefined、Null、Boolean、Number、 String 和 Symbol。
- 引用类型 Object、Array、RegExp、Date、Function
- typeof 操作符
- 对于基本类型,除 null 以外,均可以返回正确的结果。(逻辑上讲,null 值表示一个空对象指针)
- 对于引用类型,除 function 以外,一律返回 object 类型
- instanceof 操作符
- instanceof 操作符是用来确定一个对象实例的原型链上是否有原型。
- 如果知道预期的确切类型,可以使用 instanceof 来确定值的正确类型
- instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
- Object原型上的toString方法
- 调用该方法,默认返回当前对象的 [[Class]] ,这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型。
- 判断数据类型最好方式就是利用Object原型上的toString方法,结合call()方法就可以返回我们想要判断的这个数据的数据类型;- - 无论是基本类型还是引用类型都可以判断。
Object.prototype.toString.call(obj)
判断数据类型的方法,通常有三种
typeOf
instanceof
Object.prototype.toString.call()
- typeOf 能准确判断出基本类型 中的string,boolean, number, undefined, symbol 和 引用类型中的function,其余引用类型和基础类型的null因为返回结果也是object所以无法判断。
- instanceof 能判断变量是否是某个对象的实例,比图 a=[] ,a instanceof (Array) =>true , 但有个特殊,Array也是object的子类,所以a instanceof (Object) =>true
- Object.prototype.toString.call() 能判断所有数据类型,并返回"[object xx]"
采用判断数据类型的方式有三种typeof
instanceof
Object.prototype.toString
-
首先对于typeof而言基本类型除了null以外都能正确判断,而引用类型除了function以外都返回object类型
-
再instanceof运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
由于数组的原型的构造函数也在Object原型链上,所以无法准确判断数组和对象 -
最后Object.prototype.toString.call() 是一般比较通用的方法,可以准确的判断各种类型,他会返回[Object xxx] xxx就是我们相知道的数据类型
JS中判断数据类型的方式主要有三种:typeof、instanceof、Object原型下的toString方法。
Object原型下的toString方法可以判断JS中所有的类型,但是他的写法比较繁琐,所以对于typeof能判断的数字、字符串、布尔、undefined、function,我们都会优先简便的用typeof来做判断。
es6出来之后,Array可以直接用Array.isArray方法来判断。
至于instanceof,更确切的说它是用来判断一个对象,它所属的类或者说构造函数的,而且在OOP设计中更倾向用多态而不是instanceof,所以instanceof用的极少。
JavaScript
判断数据类型的方式共有四种
- typeof
- instanceof
- constructor
- Object.prototype.toString
typeof
typeof
操作符返回一个字符串,表示操作值的类型
利用 typeof
判断数据类型的语法是 typeof target
。
示例如下:
// 'number'
console.log(typeof 123)
// 'string'
console.log(typeof '123')
// 'boolean'
console.log(typeof true)
// 'symbol'
console.log(typeof Symbol(123))
// 'object'
console.log(typeof [])
// 'object'
console.log(typeof {})
// 'function'
console.log(typeof function(){})
// 'undefined'
console.log(typeof undefined)
// 'object'
console.log(typeof null)
// 'object'
console.log(typeof new Date())
// 'object'
console.log(typeof /\d/g)
// 'object'
console.log(typeof new Error())
typeof
可以准确判断除 null
之外的所有基本数据类型以及 Function
对于 null
及其他引用数据类型都返回 object
instanceof
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个 实例对象 的原型链上
利用 instanceof
判断数据类型的语法是 target instanceof constructor
。
示例如下:
// false
console.log(123 instanceof Number)
// false
console.log('123' instanceof String)
// false
console.log(true instanceof Boolean)
// false
console.log(Symbol(123) instanceof Symbol)
// true
console.log([] instanceof Array)
// true
console.log({} instanceof Object)
// true
console.log(function(){} instanceof Function)
// TypeError: Right-hand side of 'instanceof' is not an object
console.log(undefined instanceof undefined)
// TypeError: Right-hand side of 'instanceof' is not an object
console.log(null instanceof null)
// true
console.log(new Date() instanceof Date)
// true
console.log(/\d/g instanceof RegExp)
// true
console.log(new Error() instanceof Error)
用于判断操作值是否是指定构造函数的实例。
缺点:
- 不能判断基本数据类型,因为基本数据类型并不是构造函数的实例,没有原型链。
- 因为原型链的终点是
Object.protype => null
,所以引用数据类型的原型链上都会存在Object.protype
,所以引用数据类型instanceof Object
的时候都返回true
。 - 原型链可以被修改,所以结果值不一定准确。
constructor
利用 constructor
判断数据类型的语法是 target.constructor === constructor
。
示例如下:
// Number
console.log((123).constructor)
// String
console.log('123'.constructor)
// Boolean
console.log(true.constructor)
// Symbol
console.log(Symbol(123).constructor)
// Array
console.log([].constructor)
// Object
console.log({}.constructor)
// Function
console.log(function(){}.constructor)
// TypeError: Cannot read properties of undefined (reading 'constructor')
console.log(undefined.constructor)
// TypeError: Cannot read properties of null (reading 'constructor')
console.log(null.constructor)
// Date
console.log(new Date().constructor)
// RegExp
console.log(/\d/g.constructor)
// Error
console.log(new Error().constructor)
用于判断操作值是否是指定构造函数的实例,可以判断 null
和 undefined
除外的所有数据类型,之所以 null
和 undefined
不可以,是因为他们作为 JavaScript
运行环境创建时就存在的基本数据类型,不存在 constructor
属性
基本数据类型为什么会有 constructor
属性呢?
是因为基本数据类型获取 constructor
属性的时候,JavaScript
自动将基本数据类型的值转为包装对象实例,并在使用后立刻销毁实例。
缺点:constructor
属性可以被修改,所以结果值不一定准确。
Object.prototype.toString
返回对象的类型字符串.
利用 Object.prototype.toString
判断数据类型的语法是 Object.prototype.toString.call(target)
。
示例如下:
// '[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 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 Undefined]'
console.log(Object.prototype.toString.call(undefined))
// '[object Null]'
console.log(Object.prototype.toString.call(null))
// '[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()))
可以准确判断所有数据类型。