JS中的数据类型分为三大类:
简单类型
引用数据类型
symbol 创建唯一值
数据类型检测四种方式
- typeof
- instanceof
- constructor
- Object.prototype.toString.call()
typeof
语法:typeof [value]
基于 typeof检测结果
1.首先是一个字符串;
2.字符串中包含对应的类型;
3.字符串中包含对应的数据类型,例如:"number"、"object"、"undefined"、"function"、"boolean"、"symbol"...
4.因为typeof检测的结果都是字符串,所以只要两个及两个以上同时检测,最后结果必然是“string”;
typeof 1 // "number"
typeof NaN // "number"
typeof '' // "string"
typeof "24" // "string"
typeof true // "boolean"
typeof false // "boolean"
typeof undefined // "undefined"
typeof null // "object" // null特殊情况,相当于空指针对象;
function fn () {} // typeof fn => "function"
typeof typeof typeof [] // =>typeof [] => "object" =>typeof "object" => "string"
@优势
使用方便,所以在真实项目中,我们也会大量应用它来检测,尤其是在检测基本类型值(除null之外)和函数类型值的时候,它还是很方便的
@局限性
1、 typeof null => “object” , 但是null 并不是对象,是空指针对象;
2、无法细分当前值是普通对象还是数组对象等, 如: 是正则 还是数组
因为只要是对象数据类型,返回的结果都是"object";
instanceof
语法:[实例] instanceof [类]
- 用来检测某个实例是否属于这个类(对象类型)
- 属于返回TRUE,不属于返回FALSE;
@局限性:
1、不能处理基本数据类型值
2、只要在当前实例的原型链(proto)中出现过的类,检测结果都是true(用户可能会手动修改原型链的指向:example.proto 或者 在类的继承中 等情况)
arr instanceof Object // 都是true
// 如果是基本数据类型 需要通过构造函数方式创建的值(包装对象) 才能检测出来
1 instanceof Number // false
let num = new Number(1)
num instanceof Number // true
'' instanceof String // false
let str = new String('hello');
str instanceof String // true
function CreatePerson(name,age){
this.name = name;
this.age = age;
}
CreatePerson('蓝蓝',15); // this=>window 普通函数执行;
let person1 = new CreatePerson('黄黄',12);
person1 instanceof CreatePerson // =>true
constructor
@原理
在类的原型上一般都会带有CONSTRUCTOR属性,存储当前类本身,我们也是利用这一点,获取某实例的CONSTRUCTOR属性值,验证是否为所属的类,从而进行数据类型检测
@局限性
可以去随意修改对应的constructor值或者是手动给ary增加一个私有的constructor属性等;
var obj = {}
console.log(obj.constructor === Object) // true
var arr = []
console.log(arr.constructor === Array) // true
console.log(arr.constructor === Object) // false
var date = new Date()
console.log(date.constructor === Date) // true
var reg = /\d+/
console.log(reg.constructor === RegExp) // true
arr.constructor = 111; //=>设置私有属性
console.log(arr.constructor === Array); //=>false
Func.prototype={}; //=>这样原型上没有CONSTRUCTOR属性(重构了)
Object.prototype.toString.call([value])
"[object 所属类]" ,例如:"[object Array]"...
**所有的数据类型上都有toString方法,只有Object原型上的toString是检测当前实例所属类的详细信息的,其它原型的方法仅仅是转换为字符串;
@原理
1.首先基于原型链查找机制,找到Object.prototype.toString
2.把找到的方法执行,方法中的this -> obj
3.方法内部把this(obj)的所属类信息输出
=>方法执行,方法中的this是谁,就是检测谁的所属类信息
@优势
所有数据类型隶属的类信息检测的一清二楚
String/Boolean/Null/Undefined/Symbol/Object/Array/RegExp/Date/Math/Function...
console.log(Object.prototype.toString.call(1)) // "[object Number]"
console.log(Object.prototype.toString.call('a')) // "[object String]"
function func(n, m) {
return n + m;
}
let obj1 = {},
obj2 = {
name: '蓝蓝'
}; */
console.log([12, 23].toString()); //=>"12,23"
console.log(/^\d+$/.toString()); //=>"/^\d+$/"
console.log(func.toString()); //=>"function func(n, m) {...}"
console.log(obj1.toString()); //=>"[object Object]"
console.log(obj2.toString()); //=>"[object Object]"
结合每个方法,属性的优缺点,我们来封装一个简单的检测数据类型库:
let _obj = {
isNumeric: "Number",
isBoolean: 'Boolean',
isString: 'String',
isNull: 'Null',
isUndefined: 'Undefined',
isSymbol: 'Symbol',
isPlainObject: 'Object',
isArray: 'Array',
isRegExp: 'RegExp',
isDate: 'Date',
isFunction: "Function",
isWindow: 'Window'
},
_toString = _obj.toString,
_type = {};
for (let key in _obj) {
if (!_obj.hasOwnProperty(key)) break;
let reg = new RegExp("^\\[object " + _obj[key] + "\\]$");
_type[key] = function (val) {
return reg.test(_toString.call(val));
}
}
console.log(_type.isNumeric('ddd')) // =>false