今日题目:

你可以说说怎么区分变量的数据类型吗

题目解析:

我所知道并总结的数据类型判断方法一共有4种,他们分别是:

  1. Object.prototype.toString
  2. constructor
  3. typeof
  4. instanceof

接下来我就具体说说这四种方法的用法和原理吧?

得到面试官示意:

  • 不用了 -> 下一题吧
  • 微笑不说话并点头 -> 则继续向下文展开整个篇章:
  • 嗯,你可以具体说说xxx -> 说具体的方法的原理和深度剖析,请看后续篇章

Object.prototype.toString

首先,我们可以直接使用Object.prototype.toString来进行判断。因为他可能是这几个方法里可以开箱即用、且判断类型最完善的一个方法了。

用法:

  1. Object.prototype.toString.call(target) // 这里也可以用apply来改变this指向。

不用类型判断结果合集:

  1. function Person() {}
  2. Object.prototype.toString.call(2020) // [object Number]
  3. Object.prototype.toString.call('小石头') // [object String]
  4. Object.prototype.toString.call(true) // [object Boolean]
  5. Object.prototype.toString.call(undefined) // [object Undefined]
  6. Object.prototype.toString.call(null) // [object Null]
  7. Object.prototype.toString.call(Symbol('唯一的石头姐')) // [object Symbol]
  8. Object.prototype.toString.call(999n) // [object BigInt]
  9. Object.prototype.toString.call({}) // [object Object]
  10. Object.prototype.toString.call(()=>'xing.org1^') // [object Function]
  11. // 内置对象可以细分
  12. Object.prototype.toString.call([]) // [object Array]
  13. Object.prototype.toString.call(/^\d{1,4}$/g) // [object RegExp]
  14. Object.prototype.toString.call(new Date()) // [object Date]
  15. // 自定义对象不能细分类型
  16. Object.prototype.toString.call(new Person()) // [object Object]

总结

  1. 可以判断出所有类型
  2. 自定义构造函数的类型不能判断

    constructor

    除了undefined和null外,我们可以利用原型链,找到变量构造函数的name值来判断类型。

    用法

    1. '小石头'.constructor.name // String
    2. ({}).constructor.name // Object
    3. // 可以细分自定义对象类型
    4. function Person() {}
    5. (new Person()).constructor.name // Person

    image.png

    不用类型判断结果合集:

    1. function Person() {}
    2. (2020).constructor.name // Number
    3. ('小石头').constructor.name // String
    4. (true).constructor.name // Boolean
    5. // (undefined).constructor.name // 报错 TypeError: Cannot read property 'constructor' of undefined
    6. // (null).constructor.name // 报错 TypeError: Cannot read property 'constructor' of undefined
    7. (Symbol('唯一的石头姐').constructor.name) // Symbol
    8. (999n).constructor.name // BigInt
    9. ({}).constructor.name // Object
    10. (Person.constructor.name) // Function
    11. // 内置对象可以细分
    12. ([]).constructor.name // Array
    13. (/^\d{1,4}$/g).constructor.name // RegExp
    14. new Date().constructor.name // Date
    15. // 自定义对象可以细分
    16. new Person().constructor.name // Person

    总结:

  3. 因为调用undefined和null身上的属性会报错,所以需要先判断,剔除这两者。

  4. 可以细分内置对象
  5. 可以细分自定义对象
  6. 但原型链可能被修改,导致判断不准确

代码封装如下:

  1. function getConstructor(target){
  2. if(target == undefined) return target // 利用“双等”时,undefined和null一致
  3. else return target.constructor.name
  4. }

image.png

typeof

typeof 可以用来判断基本数据类型

用法:

  1. typeof '小石头' // ’string‘
  2. typeof('小石头') // 第二种写法
  3. typeof undefined // ’undefined‘

不用类型判断结果合集:

  1. function Person() {}
  2. console.log(typeof(2020)) // number
  3. console.log(typeof('小石头')) // string
  4. console.log(typeof(true)) // boolean
  5. console.log(typeof(undefined)) // undefined
  6. console.log(typeof(null)) // object
  7. console.log(typeof(Symbol('唯一的石头姐'))) // symbol
  8. console.log(typeof(999n)) // bigint
  9. console.log(typeof({})) // object
  10. console.log(typeof(Person)) // funtion
  11. // 内置对象不可以细分
  12. console.log(typeof([])) // object
  13. console.log(typeof(/^\d{1,4}$/g)) // object
  14. console.log(typeof new Date()) // object
  15. // 自定义对象不可以细分
  16. console.log(typeof new Person()) // object

总结:

  1. 判断null时会返回「’object’」(原理问题,见后边章节)
  2. 不能细分内置对象类型
  3. 常用来区分基本数据类型
  4. typeof一个不存在的变量/属性,得到undefined(暂时性死区问题,见后边章节)

    1. typeof adfadfadsf // undefined
    2. var aaa = {}
    3. typeof aaa.xxx // undefined

    instanceof

    可通过 instanceof 操作符来判断对象的具体类型,如果是指定类型返回 true,否则返回 false。

    用法:

    1. [] instanceof Array // true

    总结:

    因为其功能:只是判断指定对象是否在目标变量的原型链上,所以决定其局限性:

  5. 只能判断引用类型

  6. 但是可以细分自定义构造函数
  7. 若原型链被修改,将会导致判断不准确

撰写人:小石头