js数据类型判断有5种方法:
1.typeof,返回值为参数类型的字符串。常用于基本数据类型的判断。
2.instanceof,通过检查对象的原型链,判断对象是否指定类的实例。主要是针对引用数据类型对象进行判断。
3.constructor,使用原理是obj.constructor===obj.__proto__,与instanceof有点相似,但是constructor可以处理基本数据类型的检测。这个方法不可靠,因为对象的constructor属性可以随意修改。
4.Object.prototype.toString.call,适用于所有数据类型的判断检测,区分大小写。返回值是[object ‘数据类型’]。
5.===,主要是用与具体值的判断,undefined,null。
方法 | 基本数据类型 | 引用类型 | 特别注意 |
typeof | √ | x | NaN,object,null |
instanceof | x | √ | 主要是确定对象的继承关系 |
constructor | 部分 | √ | 可以改写,undefined和null没有constructor |
Object.prototype.toString.call | √ | √ | 使用所有类型的检测 |
typeof
typeof返回一个字符串,表示传入参数的类型。
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
// 无法准确检测 null 和 数组
typeof null // 'object'
typeof [] // 'object'
typeof new Date() // 'object'
typeof new RegExp() // 'object'
typeof {} // 'object'
typeof console.log // 'function'
// 注意NaN是Number中的一种
typeof NaN // 'number'
判断一个变量是否存在:
if(typeof a != 'undefined'){//变量存在
}
instanceof
instanceof用来检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。即检查对象是否是特定类(或构造函数)的实例。可以用来确定对象的继承关系。
格式: object instanceof Type
目的:判断 object 是不是 Type 类的实例,只能用来判断引用类型。
原理:判断 Object 的原型链上是否能找到 Type 类的原型对象。
注意:右操作数必须是class或者函数
object instanceof constructor
let Car = function() {}
let benz = new Car()
benz instanceof Car // true
instanceof的实现原理:
function instanceof(obj, constructor) {
// obj的隐式原型
let implicitPrototype = obj?.__proto__;
// 构造函数的原型
const displayPrototype = constructor.prototype;
// 遍历原型链
while (implicitPrototype) {
// 找到,返回true
if (implicitPrototype === displayPrototype) return true;
implicitPrototype = implicitPrototype.__proto__;
}
return false;
}
instanceof和typeof的区别:
- 返回值不同:typeof返回的是一个字符串,instanceof返回的是一个布尔值。
- typeof可以用来检查基本数据类型和函数,但是对数组和null处理不够准确。
- instanceof用于检查对象是否是特定类的实例,可以很好的处理继承关系,具有灵活性
constructor
constructor是该实例对象的构造函数。
格式:object.constructor
原理:object.constructor===object.__proto__,与instanceof有点类似,但是constructor可以处理基本数据类型的检测。
注意:(1)null 和 undefined 没有 constructor,constructor可以被改写,不可靠。
(2)判断数字时要使用(),(123).constructor
console.log([1,2,3].constructor);//[Function: Array]
console.log({}.constructor);//[Function: Object]
console.log((1).constructor);//[Function: Number]
console.log("abc".constructor);//[Function: String]
// 改写constructor
String.prototype.constructor = () =>{
return [];
}
console.log("abc".constructor);//[Function (anonymous)]
Object.prototype.toString.call()
object.prototype.toString(),会返回一个形如 " [obejct Type] " 的字符串。
(1)toString()未重写,返回 " [obejct Type] "。
(2)toString()在大多数情况下都会被重写,重写之后调用 toString() 并不是Object.prototype中的toString() 方法。这个时候,需要使用call(),apply(),Reflect.apply()等方法来调用,动态改变this指向。只有Object.prototype上的 toString 才能用来进行复杂数据类型的判断。
var a = {
toString() {
return "a的说明";
},
};
console.log(a.toString());// a的说明,重写之后的toString()
console.log(Object.prototype.toString.call(a));// [object Object]
console.log(Object.prototype.toString.apply(a,[]));// [object Object]
console.log(Object.prototype.toString.call("1"));//[object String]
console.log(Object.prototype.toString.call(12));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "1"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));//[object Object]