资讯专栏INFORMATION COLUMN

js中对数据类型的总结及判断数据类型的各种方法及优缺点

voyagelab / 1662人阅读

摘要:最常见的判断方法它的官方解释操作符返回一个字符串,表示未经计算的操作数的类型。另外,是判断对象是否属于某一类型,而不是获取的对象的类型。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。

js中的数据类型

js中只有六种原始数据类型和一个Object:

Boolean

Null

Undefined

Number

String

Symbol (ECMAScript 6 新定义)

Object

大家认真记清这个描述,不要到时候把Array、Date都当成js的数据类型就尴尬了。那可能会有人问,那Array和Date算什么呢,他们都属于Object,看下面分类:

Object分类
Object分为本地对象内置对象宿主对象三种
本地对象
定义:独立于宿主环境的ECMAScript实现提供的对象。简单的说就是ECMA定义的类。他们包括:
Object   Function   Array   String
Boolean   Number  Date RegExp
Error   EvalError   RangeError  ReferenceError
SyntaxError   TypeError URIError

所以Array和Date都属于对象类型,它们是本地对象。

疑问:

1.有人可能会问,为什么String也是Object类型,上面不是说了是原始类型吗?
答:原始类型中有字符串String不错,它只是表达了一种数据类型,但数据类型也有自己的类定义啊,是吧,上面的String说的就是它的类型定义,是个对象,所以当然也是引用类型了。其他同理。
看下面demo

var str1="hello";
var str2=new String("hello");
typeof str1 //string
typeof str2 //object

//如果想获取str2的字符串,可以通过str2.toString()

str1 instanceof String //false
str2 instanceof String //true
内置对象
定义:“由ECMAScript实现提供的、独立于宿主环境的所有对象,在ECMAScript程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已经被实例化了。
内置对象只有两个GlobalMath,他们其实也是本地对象,根据定义每个内置对象都是本地对象。
宿主对象
所有非本地对象都是宿主对象,即由ECMAScript实现的宿主环境提供的对象。所有BOMDOM对象都是宿主对象。
typeof

最常见的判断方法:typeof,它的官方解释:

typeof操作符返回一个字符串,表示未经计算的操作数的类型。
简单理解就是typeof是判断的是原始类型(值类型),但函数返回的是function,null返回的也是object
typeof Undefined //"undefined"
var num;
typeof num  //undefined
typeof各类型返回结果列表
类型 结果
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol (ECMAScript 6 新增) "symbol"
宿主对象(由JS环境提供) Implementation-dependent
函数对象([[Call]] 在ECMA-262条款中实现了) "function"
任何其他对象 "object"
为什么typeof null是object
在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null的类型标签也成为了 0,typeof null就错误的返回了"object"。
typeof优缺点列表
优点 缺点
判断原始类型比较方便 null返回的是object
方法返回的是function
所有的引用类型都返回object,Array、Date等不能准确定位
instanceof
定义:“instanceof 运算符用来测试一个对象(第一个参数)在其原型链中是否存在一个构造函数(第二个参数)的 prototype 属性。”
简单理解就是:instanceof是判断两个对象“最近”prototype是否一样。
另外,instanceof是判断对象是否属于某一类型,而不是获取的对象的类型。
var str1="hello";
var str2=new String("hello");
var arr=[1,2,3];
function person(){}
function man(){}
man.prototype=new person();
var m1=new person();
var m2=new man();

str1 instanceof String    //false
str2 instanceof String    //true
arr instanceof Array      //true
arr instanceof window.frames[0].Array  //false
m1 instanceof person      //true
m2 instanceof man         //true
m2 intanceof person       //true
优缺点列表
优点 缺点
判断对象的具体类型 只能判断对象,对原始类型不能判断
多全局对象时返回不正确
多全局对象解释
简单来说:多全局对象就是跨窗口或跨frame操作。
全局环境

在浏览器中,我们的脚本可能需要在多个窗口之间进行交互。多个窗口意味着多个全局环境,不同的全局环境拥有不同的全局对象,从而拥有不同的内置类型构造函数。
这可能会引发一些问题。
比如,表达式 [] instanceof window.frames[0].Array 会返回false,因为 Array.prototype !== window.frames[0].Array.prototype,因此你必须使用 Array.isArray(myObj) 或者 Object.prototype.toString.call(myObj) === "[object Array]"来判断myObj是否是数组。

根据对象的constructor判断
alert(c.constructor === Array) ----------> true
alert(d.constructor === Date) -----------> true
alert(e.constructor === Function) -------> true
注意: constructor 在类继承时会出错
eg:
      function A(){};
      function B(){};
      A.prototype = new B(); //A继承自B
      var aObj = new A();
      alert(aobj.constructor === B) -----------> true;
      alert(aobj.constructor === A) -----------> false;
而instanceof方法不会出现该问题,对象直接继承和间接继承的都会报true:
      alert(aobj instanceof B) ----------------> true;
      alert(aobj instanceof B) ----------------> true;
言归正传,解决construtor的问题通常是让对象的constructor手动指向自己:
      aobj.constructor = A; //将自己的类赋值给对象的constructor属性
      alert(aobj.constructor === A) -----------> true;
      alert(aobj.constructor === B) -----------> false; //基类不会报true了;

缺点:继承的对象判断时,不准确。感觉鸡肋。

最靠谱的方法: Object.prototype.toString.call(obj)

这种方法不存在多全局环境和Array、null返回object的情况,

原始类型和原始类型对应的引用类型声明的变量都能返回正确的值

但是这个方法对自定义类型无效,自定义类型返回的都是Object,所以自定义时还是使用instanceof

var str1="hello";
var str2=new String("hello");
var arr=[1,2,3];
function Man(){}
var man=new Man();
Object.prototype.toString.call(str1);   //[object String]
Object.prototype.toString.call(str2);   //[object String]
Object.prototype.toString.call(arr);   //[object Array]
Object.prototype.toString.call(man);   //[object Object]
Object.prototype.toString.call(null);   //[object Null]
Object.prototype.toString.call(/test/)  //[object RegExp]
优点 缺点
不存在多全局环境问题 只能判断本地对象和宿主对象
原始类型无论是字面量语法声明还是通过对应的引用类型声明都能正确判断 自定义类型都返回[object Object]
jquery.type()

就是对prototype的封装。源码附上:

type: function( obj ) {
        return obj == null ?
            String( obj ) :
            class2type[ toString.call(obj) ] || "object";
    },
对数组的判断
var arr=[1,2,3];
typeof arr   //object  分辨不出类型
arr instanceof Array   //true //受多全局环境影响
Object.prototype.toString.call(arr);  //[object Array] //推荐
Array.isArray(arr)    //true //推荐
$.type(arr)   //array  //推荐

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94351.html

相关文章

  • 前端面试题总结js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)

    摘要:并总结经典面试题集各种算法和插件前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结vue React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快...

    li21 评论0 收藏0
  • 前端面试题总结js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)

    摘要:并总结经典面试题集各种算法和插件前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结vue React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快...

    AaronYuan 评论0 收藏0
  • 前端面试题总结js、html、小程序、React、ES6、Vue、算法、全栈热门视频资源)

    摘要:并总结经典面试题集各种算法和插件前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快速搭建项目。 本文是关注微信小程序的开发和面试问题,由基础到困难循序渐进,适合面试和开发小程序。并总结vue React html css js 经典面试题 集各种算法和插件、前端视频源码资源于一身的文档,优化项目,在浏览器端的层面上提升速度,帮助初中级前端工程师快...

    pumpkin9 评论0 收藏0

发表评论

0条评论

voyagelab

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<