首先,js的数据类型分为两类,基本数据类型(值类型)和对象类型(引用类型)。
基本数据类型有:字符串、number、布尔、symbol、undefined、null.
引用数据类型:object普通对象:存储的功能;
Array数组对象:有下标,内部数据有序
Function:内部有可执行的代码
判断object对象是否是数组
1、typeof方法
该方法返回是字符串的表达形式
// 基本类型
typeof 123; //number
typeof "123"; //string
typeof true; //boolean
typeof undefined; //undefined
typeof function(){}; //function
let s = Symbol;
typeof s; //symbol
// 引用类型
typeof [1,2,3]; //object
typeof {}; //object
typeof null; //object
在使用 typeof 运算符时采用引用类型存储值和null会出现一个问题,无论引用的是什么类型的对象,它都返回 “object”
2、instanceof方法
2.1原理图:
翻译成js代码的理解:
JavaScript instanceof 运算符代码
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
var O = R.prototype;// 取 R 的显示原型
L = L.__proto__;// 取 L 的隐式原型
while (true) {
if (L === null)
return false;
if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__;
}
}
2.2instanceof 运算符的常规用法:
// 判断 foo 是否是 Foo 类的实例
function Foo(){}
var foo = new Foo();
console.log(foo instanceof Foo)//true
2.3//instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型
// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例
function Aoo(){}
function Foo(){}
Foo.prototype = new Aoo();//JavaScript 原型继承
var foo = new Foo();
console.log(foo instanceof Foo)//true
console.log(foo instanceof Aoo)//true
2.4JavaScript 原型继承机制:
很经典、全面的一张图片,此图片详细的描述了 JavaScript 各种对象的显示和隐式原型链结构,在使用instanceof方法时,如果能画出此图就稳稳地啦!
ps:1、 JavaScript 对象都有 proto 属性,但只有 Object.prototype.proto 为 null。
2.每个构造函数对象都有prototype显示原型属性
每个实例对象都有proto隐式原型属性。
3.构造函数的显示原型对象默认是空的object实例对象。
4。任何函数都是Function的实例,包括Function自己本身。
所以:
console.log(Object instanceof Object);//true
console.log(Function instanceof Function);//true
console.log(Number instanceof Number);//false
console.log(String instanceof String);//false
console.log(Number instanceof Function);//true
//Number和String的proto属性都指向Function原型对象,所以返回false
console.log(Function instanceof Object);//true
console.log(Foo instanceof Function);//true
console.log(Foo instanceof Foo);//false
但是,使用instanceof检测数组不准确:
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
var arr = [1,2,3];
xArray = window.frames[0].Array; //iframe中的构造函数
var arrx = new xArray(4,5,6);
console.log(arrx instanceof Array); //false
console.log(Array.prototype == xArray.prototype); //false
console.log(arr instanceof xArray); //false
instanceof操作符的问题在于,它假定只有一个全局环境。如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。
如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
array属于引用型数据,在传递过程中,仅仅是引用地址的传递。每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array;切记,不然很难跟踪问题!
此外,但 instanceof 只能用来判断对象类型,原始类型不可以。所有的基本类型使用instanceof方法会返回false,并且所有对象类型 instanceof Object 都是 true。
3.constructor方法
var ary = [1,23,4];
console.log(ary.__proto__.constructor==Array);//true
console.log(ary.constructor==Array)//true 这两段代码是一样的
var str = 'abc';
str.constructor = Array;
str.constructor === Array // return true
而很明显str不是数组,因为constructor可以被重写,所以不能确保一定是数组,其次,IE早期版本里面__proto__是没有定义的,另外constructor和instanceof存在同样问题,不同执行环境下,constructor判断不正确。
4. Array.isArray()
最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的,这个方法的用法如下。
if(Array.isArray(value)){
return true;
}
因为是新添加的,在不支持的浏览器上可能有兼容性,用的时候需要兼容下不支持的浏览器
5. Object.prototype.toString
在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法.返回一个‘[object 构造函数名]’字符串,每个类内部都有一个[[class]]属性,这个属性指定了字符串中的构造函数名。原生数组的构造函数名与全局作用域无关,所以在不同作用域下使用该方法能返回一致的结果。
function isArray (arg){
return Object.prototype.toString.call(arg)==='[object Array]'
}
自己可以封装一个获取变量类型的函数
function getType(obj) {
return Object.prototype.toString.call(obj).slice(8,-1);
}
var a = [1,2,3];
console.log(getType(a)); //Array
var b = function(){};
console.log(getType(b)); //Function