Object.prototype.toString.call()作为安全的类型检测方法,为什么没有满大街地被使用

我们知道,基本的类型检测用typeof,引用类型检测用instanceof,还有专门用于检查是不是数组的Array.isArray()。

let b = false;    typeof b;  //返回"boolean"
let n = 10;       typeof n;  //返回"number"
let s = "hello";  typeof s;  //返回"string"
let u = undefined;typeof u;  //返回"undefined"
let nul = null;   typeof nul;//返回"object"
let arr = [];
let reg = /[a-z]/;
let obj = {}
let fun = function(){}
arr instanceof Array;   //返回true
reg instanceof RegExp;  //返回true
obj instanceof Object;  //返回true
fun instanceof Function;//返回true
Array.isArray(arr);     //返回true
Array.isArray(obj);     //返回false

现在来看看,如果使用Object.prototype.toString.call()会是一个什么样的情况。

let b = false;    
let n = 10;       
let s = "hello";  
let u = undefined;
let nul = null; 

let arr = [];
let reg = /[a-z]/;
let obj = {}
let fun = function(){}

Object.prototype.toString.call(b)//返回"[object Boolean]"
Object.prototype.toString.call(n)//返回"[object Number]"
Object.prototype.toString.call(s)//返回"[object String]"
Object.prototype.toString.call(u)//返回"[object Undefined]"
Object.prototype.toString.call(nul)//返回"[object Null]"
Object.prototype.toString.call(arr)//返回"[object Array]"
Object.prototype.toString.call(reg)//返回"[object RegExp]"
Object.prototype.toString.call(obj)//返回"[object Object]"
Object.prototype.toString.call(fun)//返回"[object Function]"

我们稍作一下改进:

const _toString = value => Object.prototype.toString.call(value).slice(8,-1);
_toString(nul);//返回"Null"
_toString(b);  //返回"Boolean"
_toString(n);  //返回"Number"
_toString(arr);//返回"Array"
_toString(obj);//返回"Object"

从上面的例子可以看出,确实,相较于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也可能不准确。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值