您的位置 首页 java

面试题:四种判断数据类型的方法

前言

JavaScript 是一种弱类型或者说动态类型,这就意味着你不需要提前声明变量的类型,在程序运行的过程中,类型会被自动确定。这就意味着你可以使用同一个变量保存不同类型的数据:

 var data = 5 // data is Number now
data = '5' // data is String now
data = true // data is Boolean now
.......  

相信不管是在学习还是平常写业务的过程中,或多或少的都会碰到类似于— 如何判断数据类型 的这种问题。尤其是在面试中,经常被问到 — 请说出判断数组的几种方法 你知道判断数据类型有哪几种方法等等。

虽然看起来仅仅只是判断数据类型的方法,但是涉及到数据类型,原型链等各种js基础,话不多说,直接开始吧。

数据类型

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

  • 7中原始类型: Boolean Null Undefined Number BigInt String Symbol
  • object

原始值

— 其实我也是第一次知道原始值这个概念的

除Object 以外的所有类型(基本类型)都是不可以变的(值本身无法被改变) 例如:js中 字符串 是不可变的(js对字符串的操作返回了一个新字符串,但是原始字符串并没有被改变),我们称这些类型的值为“原始值”。

Boolean

对于布尔类型,永远只有true和 false 两个值。

Null

null 是一个字面量,不像 undefined ,它不是一个全局对象的一个属性。null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,也许更好理解。

在 API 中,null 常在返回类型应是一个对象,但没有关联的值的地方使用。

Undefined

一个没有被赋值的变量会有个默认值 undefined; undefined是全局对象的一个属性。

Number

根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位 二进制 格式的值(-(2^53 -1) 到 2^53 -1)。它并没有为整数给出一种特定的类型。除了能够表示浮点数外,还有一些带符号的值:+Infinity,-Infinity 和 NaN (非数值,Not-a-Number)。

BigInt

使用 BigInt,可以安全地存储和操作大整数. 常常通过在整数末尾附加 n 或调用 构造函数 来创建的。

 const a = BigInt('43243242424242424242342432')
// 43243242424242424242342432n

const b = 43243242424242424242342432n
// 43243242424242424242342432n  

String

字符串的长度是它的元素的数量。字符串一旦被创建,就不能被修改。但是,可以基于原始字符串的操作来创建新的字符串。例如:

  • String.concat() 拼接字符串

插一个问题:’1′. toString ()为什么可以调用?

 let a = new Object('1');
a.toString();
console. log ('-----a',a); // [String: '1']
a = null
console.log('-----a最终',a); // null  
  • 第一步:创建Object类实例。注意为什么不是String ?由于Symbol和BigInt的出现,对它们调用new都会报错,目前ES6规范也不建议用new来创建基本类型的包装类。
  • 第二步:调用实例方法。
  • 第三步:执行完方法立即销毁这个实例。

Symbol

Symbol 是ES6新增的一种基本数据类型。我们可以通过调用内置函数 Symbol() 创建,这个函数会动态的生成一个匿名、全局唯一的值。

 const a = Symbol();
const b = Symbol();
a === b // false

const c = Symbol('c'); // Symbol(c)  

Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象。可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分。


Symbol最大的用处就是:避免对象的键被覆盖。

基本数据和引用数据的区别

基本数据类型

  • 按值访问,可操作保存在变量中实际的值
  • 值被保存在 栈内存 中,占据固定大小的空间

引用数据类型

  • 引用类型的值是按引用访问的
  • 保存在堆内存中的对象,不能直接访问操作对象的内存空间

回归正题,下面来说说判断数据类型的方法


typeof

 typeof '5' // string
typeof 5 // number
typeof null // object
typeof undefined // undefined
typeof true // boolean
typeof Symbol('5') // symbol
typeof 5n // bigint
typeof new Object(); // object
typeof new  function (); // function  

上面的例子,对于基本数据类型来说,除了null返回的是object,其他都可返回正确的类型。 调用null为空,是因为

  • null被认为是一个空对象,因此返回了object
  • 因为任何对象都会被转化为二进制,null转为二进制则表示全为0,如果前三个均为0,js就会把它当作是对象,这是js早期遗留下来的bug

所以typeof:

  • 适用于判断(除null)基础类型,
  • 判断引用类型,除了function 全返回object类型

instanceof

  • 只能用来判断变量的原型链上是否有构造函数的 prototype 属性(两个对象是否属于原型链的关系),不一定能获取对象的具体类型
  • Instanceof 不适用判断原始类型的值,只能用于判断对象是否从属关系
 [] instanceof Array; // true
[] instanceof Object; // true

function Person() {};
const person = new Person();

person instanceof Person; // true
person instanceof Object; // true  

首先来分析一下,为什么 [] instanceof Array 为true。

  • 首先,[]. proto 的原型 是指向Array.prototype 的,说明两个对象是属于同一条原型链的,返回true
  • 同理,从代码中可以得知person instanceof Person也是返回true的,那么为什么person instanceof Object也为true呢?
  • 基于原型链的原理:从实例对象的构造函数的原型开始向上寻找,构造函数的原型又有其原型,一直向上找,直到找到原型链的顶端Object.prototype为止。如果没有,则返回null
  • 可以看出,person和Object是属于原型链的关系,所以返回true

注意:空对象{}的判断问题

 let obj1 = {}
console.log(obj1 instanceof Object) // true

let obj2 = Object.create(null)
console.log(obj2 instanceof Object) // false

let obj3 = Object.create({})
console.log(obj3 instanceof Object) // true
  

constructor

原理:每一个实例对象都可通过constructor来访问它的构造函数,其实也是根据原型链的原理来的。

 '5'.__proto__.constructor === String // true
[5].__proto__.constructor === Array // true

undefined.__proto__.constructor // Cannot read property '__proto__' of undefined

null.__proto__.constructor // Cannot read property '__proto__' of undefined  

由于undefined和null是无效的对象,因此是没有constructor属性的,这两个值不能用这种方法判断.

toString

  • Object.prototype.toString方法返回对象的类型字符串,因此可用来判断一个值的类型。
  • 因为实例对象有可能会自定义toString方法,会覆盖Object.prototype.toString,所以在使用时,最好加上call
  • 所有的数据类型都可以使用此方法进行检测,且非常精准
 Object.prototype.toString.call('5') // [object String]
Object.prototype.toString.call(5) // [object Number]
Object.prototype.toString.call([5]) // [object Array]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]  

总结

  • typeof 适合基本类型和function类型的检测,无法判断null与object
  • instanceof 适合自定义对象,也可以用来检测原生对象,在不同的iframe 和 window间检测时失效,还需要注意Object.create(null)对象的问题
  • constructor 基本能判断所有类型,除了null和undefined,但是constructor容易被修改,也不能跨iframe使用
  • tostring能判断所有类型,可将其封装为全能的DataType()判断所有数据类型

看完三件事❤️

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  1. 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  2. 关注头条号 『 JAVA后端架构 』,不定期分享原创知识。
  3. 同时可以期待后续文章ing
  4. 关注作者后台私信【 888 】有惊喜相送

文章来源:智云一二三科技

文章标题:面试题:四种判断数据类型的方法

文章地址:https://www.zhihuclub.com/186610.shtml

关于作者: 智云科技

热门文章

网站地图