JavaScript类型检测之typeof 和 instanceof 的缺陷与优化


Posted in Javascript onJanuary 13, 2016

在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;//tru
new Person instanceof Object;//true

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

JavaScript类型检测之typeof 和 instanceof 的缺陷与优化

从原型链可以看出,[]的__proto__最终指向了Object.prototype,类似的new Date()、new Person() 也会形成这样一条原型链,因此,我们用 instanceof 也不能完全精确的判断object类的具体数据类型。

优化方案

--------------------------------------------------------------------------------

对于这个问题,在阅读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"){
class2type[ toString.call( obj ) ] || "object"
}else {
return typeof obj;
}
}
}
})()

JavaScript 中 typeof 和 instanceof 常用来判断一个变量是否为空,或者是什么类型的。但它们之间还是有区别的:

typeof

typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型。

它返回值是一个字符串,该字符串说明运算数的类型。typeof 一般只能返回如下几个结果:

number,boolean,string,function,object,undefined。我们可以使用 typeof 来获取一个变量是否存在,如 if(typeof a!="undefined"){alert("ok")},而不要去使用 if(a) 因为如果 a 不存在(未声明)则会出错,对于 Array,Null 等特殊对象使用 typeof 一律返回 object,这正是 typeof 的局限性。

网上的一个小例子:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script language="javascript" type="text/javascript">
document.write ("typeof(1): "+typeof(1)+"<br>");
document.write ("typeof(NaN): "+typeof(NaN)+"<br>");
document.write ("typeof(Number.MIN_VALUE): "+typeof(Number.MIN_VALUE)+"<br>");
document.write ("typeof(Infinity): "+typeof(Infinity)+"<br>");
document.write ("typeof(\"123\"): "+typeof("123")+"<br>");
document.write ("typeof(true): "+typeof(true)+"<br>");
document.write ("typeof(window): "+typeof(window)+"<br>");
document.write ("typeof(Array()): "+typeof(new Array())+"<br>");
document.write ("typeof(function(){}): "+typeof(function(){})+"<br>");
document.write ("typeof(document): "+typeof(document)+"<br>");
document.write ("typeof(null): "+typeof(null)+"<br>");
document.write ("typeof(eval): "+typeof(eval)+"<br>");
document.write ("typeof(Date): "+typeof(Date)+"<br>");
document.write ("typeof(sss): "+typeof(sss)+"<br>");
document.write ("typeof(undefined): "+typeof(undefined)+"<br>")
</script>
<title>javascript类型测试</title>
</head>
<body>
</body>
</html>

instanceof

instance:实例,例子

a instanceof b?alert("true"):alert("false"); //a是b的实例?真:假

instanceof 用于判断一个变量是否某个对象的实例,如 var a=new Array();alert(a instanceof Array); 会返回 true,同时 alert(a instanceof Object) 也会返回 true;这是因为 Array 是 object 的子类。再如:function test(){};var a=new test();alert(a instanceof test) 会返回
谈到 instanceof 我们要多插入一个问题,就是 function 的 arguments,我们大家也许都认为 arguments 是一个 Array,但如果使用 instaceof 去测试会发现 arguments 不是一个 Array 对象,尽管看起来很像。

另外:

测试 var a=new Array();if (a instanceof Object) alert('Y');else alert('N');

得'Y'

但 if (window instanceof Object) alert('Y');else alert('N');

得'N'

所以,这里的 instanceof 测试的 object 是指 js 语法中的 object,不是指 dom 模型对象。

使用 typeof 会有些区别

alert(typeof(window)) 会得 object

大家知道JavaScript中判断函数参数类型是用typeof还是instanceof吗?

typeof只能判断js已有的几个类型,如function,object,number。

而instanceof可以判断对象是由哪个函数实例化出来的,如:

var a=function(x){};
var b=function(x){};
var c=new a(1);
var d=new a(2);

c instanceof a为true而d instanceof b为false。

而用typeof c和typeof d的结果都是object

“判断函数参数类型”需要根据你的需求来选择用哪个。

Javascript 相关文章推荐
JS实现鼠标单击与双击事件共存
Mar 08 Javascript
什么是Node.js?Node.js详细介绍
Jun 01 Javascript
如何判断微信内置浏览器(通过User Agent实现)
Sep 01 Javascript
javascript 面向对象封装与继承
Nov 27 Javascript
JavaScript代码实现txt文件的上传预览功能
Mar 27 Javascript
tracking.js页面人脸识别插件使用方法
Apr 16 Javascript
茶余饭后聊聊Vue3.0响应式数据那些事儿
Oct 30 Javascript
vue实现计算器功能
Feb 22 Javascript
js实现烟花特效
Mar 02 Javascript
如何解决vue在ios微信&quot;复制链接&quot;功能问题
Mar 26 Javascript
vue v-for出来的列表,点击某个li使得当前被点击的li字体变红操作
Jul 17 Javascript
浅谈vue中$event理解和框架中在包含默认值外传参
Aug 07 Javascript
jquery对复选框(checkbox)的操作汇总
Jan 13 #Javascript
分享javascript计算时间差的示例代码
Mar 19 #Javascript
学习JavaScript设计模式之代理模式
Jan 12 #Javascript
基于JavaScript实现TAB标签效果
Jan 12 #Javascript
JavaScript实现瀑布流布局
Jun 28 #Javascript
轻松实现JavaScript图片切换
Jan 12 #Javascript
jQuery动画效果图片轮播特效
Jan 12 #Javascript
You might like
德生PL660的电路分析和打磨
2021/03/02 无线电
PHP 下载文件时如何自动添加bom头及解释BOM头和去掉bom头的方法
2016/01/04 PHP
PHP注释语法规范与命名规范详解篇
2018/01/21 PHP
javascript 面向对象编程基础:继承
2009/08/21 Javascript
关于jquery中全局函数each使用介绍
2013/12/10 Javascript
浅析node.js中close事件
2014/11/26 Javascript
jquery简单实现网页层的展开与收缩效果
2015/08/07 Javascript
jQuery简单注册和禁用全局事件的方法
2016/07/25 Javascript
layui前段框架日期控件使用方法详解
2017/05/19 Javascript
JS表单提交验证、input(type=number) 去三角 刷新验证码
2017/06/21 Javascript
基于BootStrap实现简洁注册界面
2017/07/20 Javascript
使用socket.io实现简单聊天室案例
2018/01/02 Javascript
使用 JavaScript 创建并下载文件(模拟点击)
2019/10/25 Javascript
最全vue的vue-amap使用高德地图插件画多边形范围的示例代码
2020/07/17 Javascript
返回上一个url并刷新界面的js代码
2020/09/12 Javascript
[49:08]Secret vs VP 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
python连接sql server乱码的解决方法
2013/01/28 Python
Python中列表(list)操作方法汇总
2014/08/18 Python
在Python中使用pngquant压缩png图片的教程
2015/04/09 Python
Django imgareaselect手动剪切头像实现方法
2015/05/26 Python
python数字图像处理之高级滤波代码详解
2017/11/23 Python
python实现Zabbix-API监控
2018/09/17 Python
详解将Django部署到Centos7全攻略
2018/09/26 Python
Python字符串逆序的实现方法【一题多解】
2019/02/18 Python
Python使用微信接入图灵机器人过程解析
2019/11/04 Python
Python Mock模块原理及使用方法详解
2020/07/07 Python
CSS3中Animation动画属性用法详解
2016/07/04 HTML / CSS
html+css3实现的登录界面
2020/12/09 HTML / CSS
HTML5拖放效果的实现代码
2016/11/17 HTML / CSS
奥兰多迪士尼门票折扣:Undercover Tourist
2018/07/09 全球购物
Pamela Love官网:纽约设计师Pamela Love的精美、时尚和穿孔珠宝
2020/10/19 全球购物
国际贸易专业求职信
2014/06/04 职场文书
小学亲子活动总结
2014/07/01 职场文书
第28个世界无烟日活动总结
2015/02/10 职场文书
在人间读书笔记
2015/06/30 职场文书
win7配置本地ftp服务器的图文教程
2022/08/05 Servers