JS 类型检测:谈 typeof 和 instanceof 的缺陷与优化

boyanx4周前技术教程8

在javascript中,typeof 和 instanceof 是用来判断数据类型比较通用的两个方法,但这两种方式并不能完全解决实际中遇到的问题。因此,这篇文章的目的是通过对这两个方法介绍来分析其存在的问题和不足,并提供一个比较简单的优化方案。

typeof

typeof 返回一个表达式的数据类型的字符串,返回结果为javascript中的基本数据类型,包括:number、boolean、string、object、undefined、function等6种数据类型。

typeof 100; //number
typeof (1==1); //boolean
typeof 'onepixel'; //string
typeof {} ; //object
typeof onepixel; // undefined
typeof parseInt; // function
typeof ;//object
typeof new Date; //object   

可以看出,typeof 可以准确的判断除object以外的基础数据类型,但不能区分object类型的具体类型,比如 Array 、Date 以及自定义类。

instanceof

instanceof 本意是用来判断 A 是否为 B 的实例对象,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。 在这里需要特别注意的是:instanceof检测的是原型,那它是怎么检测的呢,我们用一段伪代码来模拟其内部执行过程:

instanceof (A,B) = {
    var L = A.__proto__;
    var R = B.prototype;
    if(L === R) {
        //A的内部属性__proto__指向B的原型对象
        return true;
    }
    return false;
}

从上述过程可以看出,当 A 的 __proto__ 指向 B 的 prototype 时,就认为A就是B的实例对象,我们再来看几个例子:

 instanceof Array; //true
{} instanceof Object;//true
new Date instanceof Date;//true

function Person{};
new Person instanceof Person;

 instanceof Object; //true
new Date instanceof Object;//true
new Person instanceof Object;//true

从上面的例子中,我们发现,虽然 instanceof 能够正确判断 是Array的实例对象,但 instanceof 认为 也是Object的实例对象,为什么呢? 这还需要从JS的原型链说起,我们首先来分析一下、Array、Object 三者之间的关系: 从instanceof能够判断出 .__proto__ 指向 Array.prototype, 而实际上 Array.prototype.__proto__ 指向了Object.prototype,
Object.prototype.__proto__ 指向了null,标志着原型链的结束。(ps:关于JS原型链请阅读:浅谈javascript原型和原型链) 因此,、Array、Object就形成了一条原型链:

从原型链可以看出, 的 __proto__ 最终指向了Object.prototype,因此,JS认为 也是Object的实例。当然,类似的new Date、new Person 也会形成这样一条原型链,因此,用 instanceof 只能够用来判断已知的数据类型,比如: instanceof Array , 而不能获取一个对象的具体数据类型。

优化方案

对于这个问题,在阅读jQuery源码时,发现 jQuery 实现了一个较好的解决方案来获取数据类型,由于源码之间存在相互调用不便于阅读和理解,因此,我按照其思路进行了整理和封装,代码如下:

(function{

    var class2type = {};
    var typeList = "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " );

    typeList.eachEach(function(item){
        class2type[ "[object " + item + "]" ] = item.toLowerCase;
    }

    return {
        getObjType:function(obj) {
 if ( obj == null ) {
 return obj + "";
 }
 
 if(typeof obj === "object" || typeof obj === "function"){

 return class2type[ toString.call( obj ) ] || "object"

 }else {
 return typeof obj;
 }
        }
    }
})

代码仅供参考,如有不同见解,欢迎交流!

by @ 一像素 2016.01

标签: jquery js

相关文章

好程序员web前端教程分享web前端都学些什么

  Web前端行业入门简单、薪资前景好,是许多IT小白跨行的首选。参加培训班是大家跨行web前端最行之有效的方法,那么,web前端培训怎么样?都学些什么内容?下面好程序员web前端教程小编给大家介绍一...

如何成为python全栈工程师

什么是Python全栈工程师?即从前端页面的实现,到后台代码的编写,再到数据库的管理,一人可以搞定一个公司网站的所有事情,真正实现全栈开发。全栈只是个概念 也分很多种类 真正的全栈工程师涵盖了web开...

分享10款非常实用的JS开发工具

JavaScript的应用在现在的Web开发中占据的地位越来越重要,好的JS开发,不仅能提升用户体验,而且能适当的减轻web服务器的压力。何况微信平台也开放JS-SDK,助力网页开发,学好JS绝对对你...

手把手详细教你优化CSS提高网站加载速度的21种方法汇总【实践】

作者:Tam Hanna 转发链接:https://www.creativebloq.com/how-to/21-ways-to-optimise-your-css-and-speed-up-your...

网络安全之从原理看懂XSS

01、XSS的原理和分类跨站脚本攻击XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets,CSS)的缩写混淆故将跨站脚本攻击缩写为XSS...

「JS优化篇」你的 if - else 代码肯定没我写的好

作者:小生方勤转发链接:https://mp.weixin.qq.com/s/JzOQ_OwAYoP5Ic1VBtCZNA前言最近部门在对以往的代码做一些优化,我在代码中看到一连串的 if(){}el...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。