欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-08 17:02:16
...

我们知道,基本的类型检测用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个字段的值可以是字符串、函数、正则表达式和数组。

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

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方法还可能被覆写。

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

做个小结吧,类型检测方法有 typeof | instanceof | Array.isArray | Object.prototype.toString.call,作为“安全”的类型检测方法Object.prototype.toString.call也可能不准确。

 

 

相关标签: js基础知识