su37josephxia/frontend-interview

Day4 - 判断数据类型的方式有哪些?

su37josephxia opened this issue · 17 comments

考察:数据类型的判断分为基本类型和引用类型

对于基本类型的数据,我们用 typeof,判断 undefinedNumber, 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不能判断值类型,但是引用类型可以,另外arrobjinstanceof 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,是相对来说比较理想的检测方式

  1. typeof
  2. instanceof
  3. constructor
  4. 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
  1. typeof 操作符
  • 对于基本类型,除 null 以外,均可以返回正确的结果。(逻辑上讲,null 值表示一个空对象指针)
  • 对于引用类型,除 function 以外,一律返回 object 类型
  1. instanceof 操作符
  • instanceof 操作符是用来确定一个对象实例的原型链上是否有原型。
  • 如果知道预期的确切类型,可以使用 instanceof 来确定值的正确类型
  • instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
  1. 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 判断数据类型的方式共有四种

  1. typeof
  2. instanceof
  3. constructor
  4. 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)

用于判断操作值是否是指定构造函数的实例。

缺点:

  1. 不能判断基本数据类型,因为基本数据类型并不是构造函数的实例,没有原型链。
  2. 因为原型链的终点是 Object.protype => null,所以引用数据类型的原型链上都会存在 Object.protype,所以引用数据类型 instanceof Object 的时候都返回 true
  3. 原型链可以被修改,所以结果值不一定准确。

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)

用于判断操作值是否是指定构造函数的实例,可以判断 nullundefined 除外的所有数据类型,之所以 nullundefined 不可以,是因为他们作为 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()))

可以准确判断所有数据类型。