文章目录

  • 前言
  • 一、数据类型有那些
  • 二、 数据类型判断方法
    • 1.typeof
    • 2.instanceof
    • 3.constructor
    • 4.Object.prototype.toString
    • 5.练习
    • 6.应用
  • 总结

前言

当我们封装一些工具类方法,需要对参数类型严格判断的时候,往往会用到类型判断,下面我介绍几种自己实用的类型判断方式


一、数据类型有那些

在ECMAScript规范中,共定义了7种数据类型,对于它的分法也是多种多样,下面我总结了一种简单清晰的分类方法:(注:Bigint将会成为一种新增数据类型,这里我们暂不介绍)

  1. 基本类型(简单类型/值类型/原始类型):布尔、数值、字符串、undefined、null、Symbol(ES6 新增)
  2. 引用类型(复杂类型):Object
    • 基本包装对象:Boolean、Number、String
    • 单体内置对象:Array、Function、Date、RegExp
    • 宿主环境对象:浏览器环境-HTMLDocument、Window;Node环境-global等

二、 数据类型判断方法

1.typeof

typeof 返回值 “object” 、“number”、“boolean”、“undefined”、“function” 、“string”、“function”、'symbol"

typeof 返回的值都是字符串类型

typeof 操作可以判断基本类型的数据,但是也存在一些特例,比如 typeof null 返回的是“object” ,因为 从逻辑上,null 这个特殊值被认为是一个对空对象的引用,表示一个空对象指针,实际上是基础类型

typeof 5          // "number"
typeof true       // "boolean"
typeof 'text'     // "string"
typeof Symbol(1)  // "symbol"
typeof undefined  // "undefined"
typeof null       // "object"

注意:因为 typeof 是一个操作符而不是函数,所以不需要参数,但是可以使用参数,执行结果是一样的

let message = "some string"
typeof message  // "string"
typeof(message) // "string"

对于引用类型的数据,typeof 判断的结果均为 “object”, 函数返回 “function” symbol 返回 ‘symbol’

typeof []             // "object"
typeof new Date()     // "object"
typeof function(){}   // "function"
typeof symbol("xx")   // "symbol"

小结:typeof 只能准确判断除 null 以外的基本类型

2.instanceof

instanceof 是用来 判断数据是否是某个对象的实例,返回一个布尔值

基本用法

// 判断 obj 是否为 Object 的实例
function Person(name) {this.name = name
}
const p = new Person('sunshine')
p instanceof Person // true// 这里的 p 是 Person 函数构造出来的,所以顺着 p 的原型链可以找到Object的构造函数
p.__proto__ === Person.prototype // true
p.__proto__.__proto__ === Object.prototype // true

缺点

  • 对于基本类型的数据,instanceof是不能直接判断它的类型的,因为实例是一个对象或函数创建的,是引用类型,所以需要通过基本类型对应的 包装对象 来判断。所以对于 null 和 undefined 这两个家伙就检测不了了~
5 instanceof Number // false
new Number(5) instanceof Number  // true
  • 因为原型链继承的关系,instanceof 会把数组都识别为 Object 对象,所有引用类型的祖先都是 Object 对象
let arr = [1, 2]
console.log(Object.prototype.toString.call(arr) === '[object Array]') // true
console.log(arr instanceof Array) // true
console.log(arr instanceof Object) // true
let fn = function(){}
console.log(fn instanceof Object)  // true

手写实现 instanceof

instanceof的核心原理是:用来检测某个实例对象的原型链上是否存在构造函数的 prototype 属性

function myInstanceof(instanceObj, constructorFun) {const prototypeObj = constructorFun.prototype // 获取构造函数的原型对象(显示原型)instanceObj = instanceObj.__proto__ // 获取实例对象的原型(隐式原型)// 循环进行查找原型 直到 Object.prototype.__proto__  === nullwhile (instanceObj) {if (prototypeObj === instanceObj) {return true}instanceObj = instanceObj.__proto__ // 重点(核心):层层向上遍历}return false
}myInstanceof('', String) // true
myInstanceof(1, String) // falsefunction Person(name) {this.name = name
}
const p = new Person('sunshine')
myInstanceof(p, Person) // true

小结

  • instanceof 可以检测所有能转换为实例对象的数据
  • 所有引用类型都是 Object 的实例

3.constructor

使用 constructor 可以查看目标构造函数,也可以进行数据类型判断。但是不能判断 null 和 undefined,因为这两个特殊类型没有其对应的包装对象。constructor和instanceof 类似,constructor 返回结果的是自己的构造函数,而 instructor 则是自己与构造函数比较返回布尔值

(5).constructor === Number     // true
"text".constructor === String  // true
true.constructor === Boolean   // true
({}).constructor === Object    // true
console.log({} instanceof Object) // true// Uncaught TypeError: Cannot read property 'constructor' of undefined
undefined.constructor === undefined  // 报错
null.constructor === null            // 报错

4.Object.prototype.toString

在判断数据类型时,我们称 Object.prototype.toString 为 “万能方法” “终极方法”,工作中也是比较常用而且准确

// 简单实现
var arr = [1, 2, 3]
Object.prototype.toString.call(arr)// 封装实现 (返回对应类型)
function type(obj) {return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase()
}// 简易实现 Array.isArray() 方法
function isArray(obj) {return type(obj) === 'array'
}
console.log(isArray(arr)) // true

深度剖析

在ECMAScript中,Object类型的每个实例都有 toString() 方法,返回对象的字符串表示,所以每个实例化的对象都可以调用 toString() 方法,并且其他数据类型也能使用 toString()

var obj = {a: 1}
console.log(obj.toString())     //"[object Object]"var flag = true
console.log(flag.toString())     // "true"var num = 1
console.log(num.toString());    // "1"

那么为什么都可以使用 toString() 方法,方法是哪里来?

我们顺着原型链,obj => obj.proto => Object.prototype,可以发现,toString()方法是定义在 Object 的原型对象 Object.prototype上的,这样 Object 的每个实例化对象都可以共享Object.prototype.toString()方法

如果不通过原型链查找,直接调用Object.prototype.toString()也可以,因为Object.prototype 也是对象,所以返回了对象的字符串表示。通过obj对象调用Object.prototype.toString()方法

我们再来分析一下不同类型的“对象”调用toString()方法,返回值有什么不同之处?

Object.prototype.toString.call/apply(obj) // "[object Object]"

Object 作为引用类型,它是一种数据结构,常被称为 Object类(但这种称呼并不妥当,JS中没有类,一切都是语法糖而已)。另外,基于Object 类型,JS还实现了其他常用的对象子类型(就是不同类型的对象),我们可以说,Object类是所有子类的父类(祖先)

上面提到的定义在 Object.prototype 上的 toString() 方法,可以说是最原始的toString()方法了,其他类型都或多或少重写了toString()方法,导致不同类型的对象调用 toString() 方法产生返回值各不相同

Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call(function(){}) // "[object Function]"
Object.prototype.toString.call('') // "[object String]"
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call() // "[object Undefined]"
Object.prototype.toString.call(new Date()) // "[object Date]"
Object.prototype.toString.call(/at/) // "[object RegExp]"

注意:纯数字不可以直接调用toString方法,因为.也可以代表数学中的小数点,js 执行引擎在做语法解析的时候,会通过.分隔符来解析上下文,但是对于 1.toString() 这样的表达式,会理解为不合理的小数,故而报错。如果想解决这个问题,可以采用以下形式,即 (1).toString()、1…toString()、1 .toString()

1.toString()      // Uncaught SyntaxError: Invalid or unexpected token
(1).toString()    // "1"
1..toString()     // "1"
1 .toString()     // "1"

小结

toString()方法是定义在 Object 的原型对象 Object.prototype上的,Object的每个实例化对象都可以共享Object.prototype.toString()方法,所以说Object.prototype.toString.call(xxx) 是类型判断的终极解决方案

5.练习

通过上面的几种判断数据类型学习,以下练习一下吧

// 如何判断一个对象是否为数组?// 1.判断是否属于数组实例
[] instanceof Array === true// 2. 通过对象的原型方法判断
Object.prototype.toString.call(arr) // es3// 3. 判断值是不是数组 (数组身上判断方法)
Array.isArray([])// 4. constructor
[].constructor === Array

6.应用

// Iview源码
function typeOf(obj) {const toString = Object.prototype.toString;const map = {'[object Boolean]'  : 'boolean','[object Number]'   : 'number','[object String]'   : 'string','[object Function]' : 'function','[object Array]'    : 'array','[object Date]'     : 'date','[object RegExp]'   : 'regExp','[object Undefined]': 'undefined','[object Null]'     : 'null','[object Object]'   : 'object'};return map[toString.call(obj)];
}
// element-ui源码
export function isString(obj) {return Object.prototype.toString.call(obj) === '[object String]';
}export function isObject(obj) {return Object.prototype.toString.call(obj) === '[object Object]';
}export function isHtmlElement(node) {return node && node.nodeType === Node.ELEMENT_NODE;
}export const isFunction = (functionToCheck) => {var getType = {};return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
};export const isUndefined = (val)=> {return val === void 0;
};export const isDefined = (val) => {return val !== undefined && val !== null;
};

总结

判断数据类型方法有很多,实际使用需要根据自己的需求使用最适合自己的方法

判断数据类型的几种方式相关推荐

  1. 检测数据类型的几种方式

    JS中检测数据类型只有四种方式 1.typeof 用来检测数据类型的运算符 [typeof value] 1)返回值:首先是一个字符串,然后包含了我们常用的数据类型,例如:"number&q ...

  2. JS-循环清空对象 判断数据类型的5种常用方法

    应用场景:一个页面具有大量数据录入功能,在数据录入保存成功之后,需要刷新页面,即清空所有的数据.因为我把所有的字段定义到一个对象中,所以要清空这个对象,如果字段少,可以直接赋值清空,但是数据多的时候, ...

  3. linux培训好还是自学好,Linux培训好还是自学好,该怎么判断自己适合哪种方式?...

    原标题:Linux培训好还是自学好,该怎么判断自己适合哪种方式? Linux是一个免费开源的操作系统,在生活中广泛应用,也因为其简单易用的特性,很多企业.软件也越来越青睐于使用Linux系统,百度.阿 ...

  4. java 判断数组已经存满_详解Java中数组判断元素存在几种方式比较

    1. 通过将数组转换成List,然后使用List中的contains进行判断其是否存在 public static boolean useList(String[] arr,String contai ...

  5. 字符串转int数据类型的三种方式

    方法一: Integer.valueOf( ) 它将返回一个包装器类型 Integer,当然可以通过自动拆箱的方式将其转成 int 类型. String a = "100"; St ...

  6. js中判断数据类型的几种实用方法

    前言 最近项目中有不少地方需要判断数据类型,但是判断数据类型也有好几种方法,并且每种方法判断的数据类型也有局限性,所以想总结一下,方便以后查阅. 分别是 typeof ,instanceof,Obje ...

  7. JS判断数据类型的5种方法

    我们先来了解一下JS中数据类型有哪些 基本数据类型(值类型):String.Number.boolean.null.undefined.symbol(es6新增的) 引用数据类型 (引用类型):obj ...

  8. js 判断数据类型的四种方法

    1,typeof typeof 返回的数据类型有 undefined boolean (true,false) string symbol number function object 注意  typ ...

  9. 判断数据类型的5种方法

    1. typeof 可以判断数据类型,它返回表示数据类型的字符串(返回结果只能包括number,boolean,string,function,object,undefined): 可以使用typeo ...

最新文章

  1. Python:操作文件
  2. python torch exp_Python:PyTorch 保存和加载训练过的网络 (八十)
  3. 首个AI国际标准有望明年出台,创新工场等多家国内公司已参与
  4. Vue中的 computed 和 watch的区别
  5. Java 并发编程之 Callable 和 Future
  6. 转载一篇写的简单易懂的lvs用法
  7. dw中html颜色的设置颜色代码,利用Dreamweaver(DW)快速输入CSS颜色代码值
  8. 招聘网站数据分析岗位数据分析(Excel实现)
  9. mib浏览器_大众汽车的第二代MIB信息娱乐系统图解
  10. 11 空间平面方程 : 参数方程、向量式方程、行列式方程、三点式方程、点法式方程、一般方程
  11. c语言实现字符串连接
  12. Halcon create_pose算子帮助文档翻译
  13. 携程apollo从服务端安装,再到客户端的使用,第一次搭建,看我就对了(一个简单的入门demo)
  14. 被顶级机构押注的6大新公链 公链之争谁更硬核?
  15. STM32固件库(Standard Peripheral Libraries )官网下载方法
  16. 3-33在图 3-31中,以太网交换机有6个接口,分别接到5台主机和一个路由器。在下面表中的“动作”一栏中,表示先后发送了4个帧。假定在开始时,以太网交换 机的交换表是空的。试把该表中其他的栏目都填写
  17. 使用selenium模块自动打开淘宝并进行搜索
  18. 软件开发好用的工具推荐
  19. Qt用代码实现菜单栏(MenuBar)和工具栏(ToolBar)
  20. 【android studio】

热门文章

  1. 上交大计算机复试机师难不难,一个去年考交大复试被刷的人给大家一点建议(更新)...
  2. python投掷骰子实验实验结论_博饼伤我心我,决定用Python对投骰子(色子)做数据分析...
  3. golang基础教程(十五)文件操作
  4. Calibre 使用合集
  5. 极品时刻表2007.9.2(方便大家查火车时间)
  6. Android开发_ZXing库二维码应用
  7. 2.Objection 环境配置,自动化分析和插件
  8. 职场中你忽略的细节,都是别人晋升的秘密
  9. 服装商城APP开发功能
  10. Charset编码问题导致的中文乱码