数据类型分析和判断

数据类型分类和判断

JavaScript中有6种数据类型:数字(number)、字符串(string)、布尔值(boolean)、undefined、null、对象(Object)。其中对象类型包括:数组(Array)、函数(Function)、还有两个特殊的对象:正则(RegExp)和日期(Date)。
复杂数据类型(引用类型):
在存储时变量中存储的仅仅是地址(引用)
通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等;
【分类】
在这里插入图片描述
【判断】
1.typeof
typeof返回一个表示数据类型的字符串,返回结果包括:number、string、boolean、object、undefined、function。typeof可以对基本类型number、string 、boolean、undefined做出准确的判断(null除外,typeof null===“object”);而对于引用类型除了function之外返回的都是object。但当我们需要知道某个对象的具体类型时,typeof就显得有些力不从心了。

	console.log(typeof 1);// number 有效
    console.log(typeof ""); //string 有效
    console.log(typeof true); //boolean 有效
    console.log(typeof undefined); //undefined 有效
    console.log(typeof null); //object 无效
    console.log(typeof new Function());// function 有效
    console.log(typeof []);//object 无效
    console.log(typeof new Date());//object 无效
    console.log(typeof new RegExp()); //object 无效

2、instanceof
当我们需要知道某个对象的具体类型时,可以用运算符 instanceof,instanceof操作符判断左操作数对象的原型链上是否有右边这个构造函数的prototype属性,也就是说指定对象是否是某个构造函数的实例,最后返回布尔值。 检测的我们用一段伪代码来模拟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的实例.

function Person(){};
    console.log([] instanceof Array);   //true
    console.log([] instanceof Object);//true
    console.log(new Date() instanceof Date);//true
    console.log(new Date() instanceof Object);//true
    console.log(new Person() instanceof Person);//true
    console.log(new Person() instanceof Object);//true

我们发现,虽然 instanceof 能够判断出 [] 是Array的实例,但它认为 [] 也是Object的实例,为什么呢? 我们来分析一下**[]、Array、Object** 三者之间的关系: 从instanceof 能够判断出 [].proto 指向 Array.prototype, 而 Array.prototype.proto 又指向了Object.prototype,Object.prototype.proto 指向了null,标志着原型链的结束。因此,[]、Array、Object就形成了如下图所示的一条原型链:
在这里插入图片描述
从原型链可以看出,[] 的 proto 直接指向Array.prototype, 间接指向Object.prototype, 所以按照 instanceof 的判断规则,[] 就是Object的实例。
【注意:】instanceof运算符只能用于对象,不适用原始类型的值。
3、constructor
constructor属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。

function F(){};
    var f = new F();
    console.log(f.constructor === F);// true

但是 constructor 属性易变,不可信赖,这个主要体现在自定义对象上,当开发者重写prototype后,原有的constructor会丢失

 function F() { };
    var f = new F();
    console.log(f.constructor === F);// true
   
    F.prototype = {
      _name: 'Eric',
    };
    var f = new F();
    console.log(f.constructor === F);// false
function F() { };
    var f = new F();
    console.log(f.constructor === F);// true
   
    F.prototype = {
      _name: 'Eric',
    };
    //var f = new F();
    console.log(f.constructor === F);// true
function F() { };
    var f = new F();
    console.log(f.constructor === F);// true
   
    F.prototype = {
      _name: 'Eric',
    };
    f = new F();
    console.log(f.constructor === F);// false

注意细微差别。
因此,为了规范,在重写对象原型时一般都需要重新给constructor赋值,以保证实例对象的类型不被改写。

function F() { };
    var f = new F();
    console.log(f.constructor === F);// true

    F.prototype = {
      constructor: F,
      _name: 'Eric',
    };
    var f = new F();
    console.log(f.constructor === F);  // true 

4、Object.prototype.toString
toString是Object原型对象上的一个方法,该方法默认返回其调用者的具体类型,更严格的讲,是 toString运行时this指向的对象类型, 返回的类型格式为[object,xxx],xxx是具体的数据类型,其中包括:String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,… 基本上所有对象的类型都可以通过这个方法获取到。

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
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([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object Window]

需要注意的是,必须通过Object.prototype.toString.call来获取,而不能直接 new Date().toString(), 从原型链的角度讲,所有对象的原型链最终都指向了Object, 按照JS变量查找规则,其他对象应该也可以直接访问到Object的toString方法,而事实上,大部分的对象都实现了自身的toString方法,这样就可能会导致Object的toString被终止查找,因此要用call来强制执行Object的toString方法。
【总结】
1、typeof可以准确地判断出基本类型,但是对于引用类型除function之外返回的都是object;
2、已知是引用类型的情况可以选用instanceof或constructor方法进行具体类型的判断:
instanceof是基于原型链的;
3、constructor 属性易变,不可信赖,为了规范,在重写对象原型时一般都需要重新给constructor赋值,以保证实例对象的类型不被改写;
4、Object.prototype.toString.call() 通用但很繁琐。
【补充】
The latest ECMAScript standard defines nine types:
Six Data Types that are primitives, checked by typeof operator:

undefined : typeof instance === “undefined”
Boolean : typeof instance === “boolean”
Number : typeof instance === “number”
String : typeof instance === “string”
BigInt : typeof instance === “bigint”
Symbol : typeof instance === “symbol”

Structural Types:
Object : typeof instance === “object”. Special non-data but Structural type for any constructed object instance also used as data structures: new Object, new Array, new Map, new Set, new WeakMap, new WeakSet, new Date and almost everything made with new keyword;

Function : a non-data structure, though it also answers for typeof operator: typeof instance === “function”. This is merely a special shorthand for Functions, though every Function constructor is derived from Object constructor.

Structural Root Primitive:
null : typeof instance === “object”. Special primitive type having additional usage for its value: if object is not inherited, then null is shown.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值