基本的类型检测用typeof,引用类型检测用instanceof,还有专门用于检查是不是数组的Array.isArray()
let a = "b"
let b = true
let c = '123'
let d = 123
function e(){}
let f = undefined
let g = null
let h = /[a-z]/
let i = {}
let k = [1,2,3]
typeof 运行结果
typeof a 'string'
typeof b 'boolean'
typeof c 'string'
typeof d 'number'
typeof e 'function'
typeof f 'undefined'
typeof g 'object'
typeof h 'object'
typeof i 'object'
typeof k 'object'
instanceof
e instanceof Function true
h instanceof RegExp true
i instanceof Object true
k instanceof Array true
Array.isArray(k) true
Array.isArray(i) false
Object.prototype.toString.call()
Object.prototype.toString.call(a) '[object String]'
Object.prototype.toString.call(b) '[object Boolean]'
Object.prototype.toString.call(c) '[object String]'
Object.prototype.toString.call(d) '[object Number]'
Object.prototype.toString.call(e) '[object Function]'
Object.prototype.toString.call(f) '[object Undefined]'
Object.prototype.toString.call(g) '[object Null]'
Object.prototype.toString.call(h) '[object RegExp]'
Object.prototype.toString.call(i) '[object Object]'
Object.prototype.toString.call(k) '[object Array]'
去除object
const _toString = function(val){
return Object.prototype.toString.call(val).slice(8,-1)
}
_toString (a) 'String'
_toString (b) 'Boolean'
_toString (c) 'String'
_toString (d) 'Number'
_toString (e) 'Function'
_toString (f) 'Undefined'
_toString (g) 'Null'
_toString (h) 'RegExp'
_toString (i) 'Object'
_toString (k) 'Array'
相较于typeof、instanceof、Array.isArray,Object.prototype.toString.call更可靠,甚至null,它都检测出来了
webpack源码更青睐typeof,instanceof,和Array.isArray,比如截取的这段代码,用来解析module.rules中某个规则的test、include和exclude字段,这3个字段的值可以是字符串、函数、正则表达式和数组。
Vue源码做类型检测时,也很喜欢typeof,instanceof 和Array.isArray()。只是在做严格的类型检测时,会使用到Object.prototype.toString。
function isPrimitive(value){
return (
typeof value === "string" ||
typeof value === "number" ||
typeof value === "symbol" ||
typeof value === "boolean"
);
}
function isPromise(val){
return (
isDef(val) &&
typeof val.then === "function" &&
typeof val.catch === "function"
)
}
function isObject(obj){
return obj!==null && typeof obj === "object";
}
//作严格的类型检测时,会用到Object.prototype.toString
var _toString = Object.prototype.toString;
function toRawType(value){
return _toString.call(value).slice(8,-1);
}
function isPlainObject(obj){
return _toString.call(obj) === '[object Object]';
}
function isRegExp(v){
return _toString.call(v) === '[object RegExp]';
}
日常开发中,typeof,instanceof 和Array.isArray()能够满足所需,Object.prototype.toString.call更像是锦上添花,但是,Object.prototype.toString.call有原生的限制,它拿非原生构造函数没啥办法。
class Point{
constructor(x,y){
this.x = x;
this.y = y;
}
toValue(){
return this.x+this.y;
}
}
let p = new Point(1,2);
Object.prototype.toString.call(p); //返回"[object Object]"
p instanceof Point; //返回true
注意:Object.prototype.toString方法还可能被覆写。
类型检测方法有 typeof | instanceof | Array.isArray | Object.prototype.toString.call, “安全”的类型检测方法Object.prototype.toString.call
实现一个函数clone,可以对js中的5种主要的数据类型(包括number string object array Boolean)进行值复制
因为toString为Object的原型方法,而Array,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串......),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转化为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。我们可以验证一下,将数组的toString方法删除
var arr=[1,12,13];
console.log(Array.prototype.hasOwnProperty("toString"));//true
console.log(arr.toString());//1,2,3
delete Array.prototype.toString;//delete操作符可以删除实例属性
console.log(Array.prototype.hasOwnProperty("toString"));//false
console.log(arr.toString());//"[object Array]"
demo
function getDataType(data){
var getType=Object.prototype.toString;
var myType=getType.call(data);//调用call方法判断类型,结果返回形如[object Function]
var typeName=myType.slice(8,-1);// [object Function],即取除了“[object ”的字符串。 ]"
var copyInfo='';//复制后的数据
//console.log(data+" is "+myType);
switch(typeName){
case 'Number': copyInfo=data-0;
break;
case 'String': copyInfo="'"+data+"'";
break;
case 'Function': copyInfo=data;
break;
case 'Null': copyInfo=null;
break;
case 'Undefined': copyInfo="Undefined";
break;
case 'Array':
copyInfo=[];//先将copyInfo变为空数组
for(var i=0;i<data.length;i++){
copyInfo[i]=data[i];//将data数组数据逐个写入copyInfo
}
break;
case 'Object':
copyInfo={};//先将copyInfo变为空对象
for(var x in data){
copyInfo[x]=data[x];
}
break;
case 'Boolean': copyInfo=data;
break;
default : copyInfo=data;
break;
}
return copyInfo;
}