问题描述:判断变量为数组还是对象
一、instanceof
原理如下:
官方:
instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象原型链中的任何位置。即
instanceof运算符用于通过查找原型链来检查某个变量是否为某个类型数据的实例,使用instanceof运算符可以判断一个变量是数组还是对象
白话文:
如果 a instanceof B ,那么 a 必须要是个对象,而 B 必须是一个合法的函数。在这两个条件都满足的情况下:判断 B 的 prototype 属性指向的原型对象( B.prototype )是否在对象 a 的原型链上。如果在,则返回true;如果不在,则返回false。简而言之, instanceof 的原理其实就是一个查找原型链的过程。
instanceof返回一个布尔值,表示对象是否为某个构造函数的实例。instanceof的左边是实例对象,右边是构造函数,它会检查右边构造函数是否在左边实例对象的原型链上。
var a = [1, 2, 3];
console.log(a instanceof Array); // true
console.log(a instanceof Object); // true
//从此我们可以看出a既是数组,也是对象
var userInfo = { userName: "zhangsan" };
console.log(userInfo instanceof Array); // false
console.log(userInfo instanceof Object); // true
//userInfo只是对象,而不是数组
二、为什么typeof不能用来判断呢?
你知道typeof可以判断出哪几种类型呢?
答: object、function、number、symbol、string、undefined、boolean
我们能够使用typeof判断变量的身份,判断字符串得到string,数字和NaN得到number,函数会得到function等,但是对于对象{ } 、数组[ ] 、null 都会返回object,详细请看js数据类型,这就是typeof的局限性,并不能准确的判断该变量的"真实身份"。
typeof 操作符唯一的目的就是检查数据类型
原因:
js在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息。
000: 对象
010: 浮点数
100: 字符串
110: 布尔
1: 整数
对于null 和 undefined 是有点特殊的。
null的机器码均为0,所以它的低位3位也是000,因此就是object。
undefined:用 −2^30 整数来表示
三、Constructor
let arr = new Array();
let obj = {};
console.log(arr.constructor === Array); //true
console.log(arr.constructor === Object); //false
console.log(obj.constructor === Object); //true
四、Object.prototype.toString.call()
每种引用类型都会直接或间接继承Object类型,因此它们都包含toString( )函数。
不同数据类型的toString( )函数返回值也不一样,所以通过toString( )函数就可以判断一个变量是数组还是对象,当然,这里我们需要用到call方法来调用Object原型上的toString( )函数来完成类型的判断。
let arr = new Array();
let obj = {};
console.log(Object.prototype.toString.call(arr)); //[object Array]
console.log(Object.prototype.toString.call(obj)); //[object Object]
Object.prototype.toString.call()方法可以精准判断变量类型,它返回[object constructorName]的字符串格式,这里的constructorName就是call参数的函数名
五、总结
判断简单数据类型可以用typeof,判断数组,对象使用instanceof,constructor和Object.prototype.toString.call(),最好使用Object.prototype.toString.call(),更加精准