判断JS数据类型的方法
在 ECMAScript 规范中,一共定义了7种数据类型,分别分为 原始(基本)类型 和 引用类型 两大类,
原始(基本)类型 :String Number Boolean Undefined Null Symbol
引用类型 : Object
Symbol : 是 ES6引入的一种新的原始数据类型Symbol,表示独一无二的值。
首先我们定义几个变量备用:
let a = "string";
let b = 111;
let c = true;
let d = Symbol();
let e = "";
let f = null;
let g = new Object()
let h = [1,2,3];
let i = function (){
console.log("i");
}
let j = new Date()
1、typeof
typeof 是一个操作符,右侧跟一个一元表达式,并返回这个表达式的数据类型,此方法返回的都是 字符串(全小写字母)数据类型
console.log(typeof a); //string
console.log(typeof b); //number
console.log(typeof c); //boolean
console.log(typeof d); //symbol
console.log(typeof e); //string
console.log(typeof f); //object
console.log(typeof g); //object
console.log(typeof h); //object
console.log(typeof i); //function
console.log(typeof j); //object
注 : 不能判断 Undefined Null
2、instanceof
instanceof 检测的是原型,来判断A是否为B的实例,如果A是为B的实例,返回true,否则返回 false
使用一段伪代码来模拟其内部执行过程。
instanceof(A,B) = {
var L = A.__proto__;
var R = B.prototype;
if(L === R){
// A的内部属性 __proto__ 指向 B 的原型对象
return true;
}
return false
}
console.log([] instanceof Array); // true
console.log([] instanceof Object); // true
console.log({} instanceof Array); // false
console.log(new Date('2019/01/05') instanceof Date); // 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的实例。依次类推,类似的 new Date()、new Person() 也会形成一条对应的原型链 。因此,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。
当然,instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例。
let person = function () {
}
let programmer = function () {
}
programmer.prototype = new person()
let nicole = new programmer()
nicole instanceof person // true
nicole instanceof programmer // true
3、constructor
当一个函数 A 被定义时,JS引擎就会为 A 添加 prototype 原型,然后在 prototype 上添加 constructor 属性,并让其指向 A 的引用, A 利用原型对象的 constructor 属性引用了自身,当 A 作为构造函数创建对象时,原型上的 constructor 属性被遗传到了新创建的对象上,从原型链角度讲,构造函数F就是新对象的类型。这样做的意义是,让对象诞生以后,就具有可追溯的数据类型。
// 全为 true
console.log(a.constructor === String);
console.log(b.constructor === Number);
console.log(c.constructor === Boolean);
console.log(d.constructor === Symbol);
console.log(e.constructor === String);
console.log(g.constructor === Object);
console.log(i.constructor === Function);
console.log(document.constructor === HTMLDocument);
console.log(window.constructor === Window);
注 : null和undefined是无效的对象,因此是不会有constructor存在的。
4、Object.prototype.toString()
每个对象都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString() 方法被每个 Object 对象继承。如果此方法在自定义对象中未被覆盖,toString() 返回 “[object type]”,其中 type 是对象的类型。
注 : 对于Object对象,直接调用toString()就能返回 [object Object] ,而对于其他对象,则需要通过call、apply来调用才能返回正确的类型信息。
console.log(Object.prototype.toString({a:1})); // [object Object]
console.log(Object.prototype.toString.call('')); // [object String]
console.log(Object.prototype.toString.call(1)); // [object Number]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call(Symbol)); // [object Function]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]