js中数据类型有8种:
基本数据类型(原始数据类型)(6种):
number, string, boolean,null, undefined, symbol(es6新增)
引用数据类型:
object, function
1. 最常用方法 -- typeof
缺点: 不能细分对象,数组,时间对象
typeof 运算符的最终结果有7种(typeof null === 'object')
"number" // typeof 123 ; typeof NaN "string" // typeof "123" "boolean" // typeof true "function" // function f() {}; typeof f "object" // typeof {}; typeof [];typeof new Date(); typeof null; typeof window "undefined" // typeof undefined; typeof 未定义变量 "symbol" // typeof Symbol();
2. 判断对象类型--instanceof
instanceof 的原理是检查右边构造函数的prototype属性是否在左边实例对象的原型链上。
instanceof(a, B) {// a代表实例对象;b代表构造函数 a = a.__proto__; B = B.prototype; while(true) { if (a === null) {// 原型链顶层 return false; } if(a === B) { return true; } a = a.__proto__; } }
instanceof命令本质上调用的是构造函数上的静态方法[Symbol.hasInstance]。
⚠️:原生的构造函数该方法不能被覆写。
可以通过在自定义的构造函数上添加静态方法[Symbol.hasInstance]自定义实现instanceof 命令。
class IsStr{ static [Symbol.hasInstance](x) { return typeof x === 'string'; } } console.log('' instanceof IsStr); //true
所以下面的实例如果 instanceof Object 全部为true
([2]) instanceof Array -> true (new Date()) instanceof Date -> true (function(){}) instanceof Function -> true ({}) instanceof Object -> true
null,undefined 使用该运算法的时候,返回值永远是 false
三 判断对象类型 constructor
constructor
属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。
constructor属性是prototype对象上的属性,实例对象本身没有这个属性,调用的是原型对象上的constructor。
因为js规定:P.prototype.constructor === P
(new Date()).constructor === Date -> true ([2]).constructor === Array -> true (function(){}).constructor === Function -> true ({}).constructor === Object -> true
⚠️PS:instanceof 和 constructor 两者区别:
instanceof考虑的是原型链
function A(){}; function B(){}; A.prototype = new B(); // 构造函数A的原型是B的实例 var aobj = new A(); console.log(aobj.constructor === B) / //true console.log(aobj.constructor === A) //false console.log(aobj instanceof A) //true console.log(aobj instanceof B) //true
类不通过prototype属性进行原型继承,es6的class中prototype是只读属性。
class A {} Object.getOwnPropertyDescriptor(A, "prototype"); /* { "value": constructor, "writable": false, "enumerable": false, "configurable": false } */
class A{}; class B{}; A.prototype = new B(); var aobj = new A(); console.log(aobj.constructor === B) //false console.log(aobj.constructor === A) //true console.log(aobj instanceof A) //true console.log(aobj instanceof B) //false
四. 通用方法
缺点: 只能判断原生的数据类型,自定义的无法判断。
Object.prototype.toString() 默认返回类型字符串。所有的值都继承该方法。
但是数组、字符串、函数、Date 对象都又定义了属于自己的toString方法,覆盖了继承的Object.prototype的toString()方法。
所以为了可以判断所有的类型,统一使用Object.prototype.toString.call(value),来判断数据类型。
call方法是用于改变this的指向,value就是方法运行时的实例对象,如果value是原始值,会自动将其转为对应的包装对象。
- 数值:返回
[object Number]
。 - 字符串:返回
[object String]
。 - 布尔值:返回
[object Boolean]
。 - undefined:返回
[object Undefined]
。 - null:返回
[object Null]
。 - 数组:返回
[object Array]
。 - arguments 对象:返回
[object Arguments]
。 - 函数:返回
[object Function]
。 - Error 对象:返回
[object Error]
。 - Date 对象:返回
[object Date]
。 - RegExp 对象:返回
[object RegExp]
。 - 其他对象:返回
[object Object]
。
*************判断一个变量是否是对象的方法*************
function isObject(value) { return value === Object(value) } // 注意,原始类型的值通过Object()函数之后,会变成对应的包装对象; // 对象(数组,对象,函数)等于本身
****************************************************