js检测数据类型的几种方法总结

网友投稿 522 2022-11-15

js检测数据类型的几种方法总结

js检测数据类型的几种方法总结

文章目录

​​一、typeof​​​​二、instanceof​​

​​1. 基础类型​​​​2. 复杂类型(万物皆对象)​​

​​三、constructor​​​​四、Object.prototype.toString.call()​​

​​Object.prototype.toString.call(obj)类型检测原理​​

一、typeof

​​typeof​​​在对值类型​​number​​​、​​string​​​、​​boolean ​​​、​​symbol​​​、​​undefined​​​、​​function​​的反应是精准的;但对于​​对象{ }​​​ 、​​数组[ ]​​​ 、​​null ​​​都会返回​​object​​

console.log(typeof ""); // stringconsole.log(typeof 1); // numberconsole.log(typeof NaN); // numberconsole.log(typeof true); // booleanconsole.log(typeof Symbol(1)) // "symbol"console.log(typeof undefined); // undefinedconsole.log(typeof function(){}); // functionconsole.log(typeof null); // object (巨坑...)console.log(typeof []); // objectconsole.log(typeof {}); //object

二、instanceof

​​typeof​​​运算符把​​对象​​​、​​数组​​​、​​null​​​都返回​​object​​​,为了弥补这一点,​​instanceof​​从原型的角度,来判断该对象是谁的实例。

用​​instanceof​​ 判断一个实例是否属于某种类型​​instanceof​​ 运算符只能用于对象,不能用于原始类型的值

// 检测构造函数B的原型是否有出现在对象A的原型链上。A instanceof B [] instanceof Array // true[].__proto__ == Array.prototype // true

1. 基础类型

console.log("1" instanceof String); // falseconsole.log(1 instanceof Number); // falseconsole.log(NaN instanceof Number); // falseconsole.log(true instanceof Boolean); // false

上面之所以都返回​​false​​是因为不是对象,而是基本类型。

封装成对象后才返回​​true​​,如下:

console.log(new String("1") instanceof String); // trueconsole.log(new Number(1) instanceof Number); // trueconsole.log(new Number(NaN) instanceof Number); // trueconsole.log(new Boolean(true) instanceof Boolean); // true

new是封装成对象,而没有new的只是基础类型转换,还是基础类型

一个是引用类型,一个是基本类型

console.log(new String("1"), "1");console.log(new Number(1), 1);console.log(new Number(NaN), NaN);console.log(new Boolean(true), true);

2. 复杂类型(万物皆对象)

console.log([] instanceof Array); // trueconsole.log([] instanceof Object); // trueconsole.log({} instanceof Object); //trueconsole.log(function(){} instanceof Function); // trueconsole.log(function(){} instanceof Object); // trueconsole.log((new Number(1)) instanceof Number); // trueconsole.log((new Number(1)) instanceof Object); // true

小坑

console.log(undefined instanceof undefined); // 报错console.log(null instanceof null); // 报错

巨坑

console.log(null instanceof Object); // falseconsole.log(typeof null); // object

三、constructor

constructor 是每个实例对象都拥有的属性

function Hello() {}; // 构造函数var h = new Hello(); // 实例化对象console.log(Hello.prototype.constructor == Hello); // trueconsole.log(h.constructor == Hello); // true ()

console.log(("1").constructor === String); // trueconsole.log((1).constructor === Number); // trueconsole.log((NaN).constructor === Number); // trueconsole.log((true).constructor === Boolean); // trueconsole.log(([]).constructor === Array); // trueconsole.log((function () {}).constructor === Function); // trueconsole.log(({}).constructor === Object); // trueconsole.log((Symbol(1)).constructor === Symbol); // trueconsole.log((null).constructor === Null); // 报错console.log((undefined).constructor === Undefined); // 报错

用costructor来判断类型看起来是完美的,然而,如果我创建一个对象,更改它的原型,这种方式也变得不可靠了。

function Fn(){};Fn.prototype=new Array(); // 改变原型var f=new Fn();console.log(f.constructor===Fn); // falseconsole.log(f.constructor===Array); // true

四、Object.prototype.toString.call()

​​完美精准​​

const a = Object.prototype.toString;console.log(a.call(1)); // [object Number]console.log(a.call("1")); // [object String]console.log(a.call(NaN)); // [object Number]console.log(a.call(true)); // [object Boolean]console.log(a.call(Symbol(1))); // [object Symbol]console.log(a.call(null)); // [object Null]console.log(a.call(undefined)); // [object Undefined]console.log(a.call([])); // [object Array]console.log(a.call({})); // [object Object]console.log(a.call(function () {})); // [object Function]function Fn(){};Fn.prototype=new Array(); // 改变原型var f=new Fn();console.log(a.call(Fn)); // [object Function]

稍微简单封装下:

// 定义检测数据类型的功能函数function checkedType(target) { return Object.prototype.toString.call(target).slice(8, -1);}console.log(checkedType(1)); // Numberconsole.log(checkedType("1")); // Stringconsole.log(checkedType(NaN)); // Numberconsole.log(checkedType(true)); // Booleanconsole.log(checkedType(Symbol(1))); // Symbolconsole.log(checkedType(null)); // Nullconsole.log(checkedType(undefined)); // Undefinedconsole.log(checkedType([])); // Arrayconsole.log(checkedType({})); // Objectconsole.log(checkedType(function () {})); // Function

Object.prototype.toString.call(obj)类型检测原理

首先,这句话的意思是让我们用​​Object​​​原型上的​​toString​​​方法作用在传入的​​obj​​​的上下文中(通过​​call​​​将​​this​​​指向​​obj​​​),那么我们知道数组本身也有​​toString()​​​方法,那我们为什么非要用​​Object​​上的呢?

Object.toString() // "function Object() { [native code] }"Object.prototype.toString() // "[object Object]"

​​Object​​​输出的是其函数体​​function Object() { [native code] }​​​,而​​Object​​​上输出的是其类型。 我们可以看出​​​Object​​​对象和它的原型链上各自有一个​​toString()​​方法,第一个返回的是一个函数,第二个返回的是值类型。

​​toString​​​为​​Object​​​的原型方法,而​​Array 、Function​​等类型作为Object的实例,都重写了​​toString​​​方法。不同的对象类型调用​​toString​​方法时,根据原型链的知识,调用的是对应的重写之后的​​toString​​方法(​​Function​​​类型返回内容为函数体的字符串,​​Array​​​类型返回元素组成的字符串…),而不会去调用​​Object​​​上原型​​toString​​​方法(返回对象的具体类型),所以采用​​obj.toString()​​​不能得到其对象类型,只能将​​obj​​​转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用​​Object​​​上原型​​toString​​方法。

我们可以验证一下,将数组的​​toString​​方法删除,看看会是什么结果:

var arr=[1,2,3];console.log(Array.prototype.hasOwnProperty("toString"));//trueconsole.log(arr.toString());//1,2,3delete Array.prototype.toString;//delete操作符可以删除实例属性console.log(Array.prototype.hasOwnProperty("toString"));//false// 删除后的数组再次使用 toString() 时,会向上层访问这个方法,即 Object 的 toString()console.log(arr.toString());//"[object Array]"

当我们把Array自身的toString()方法删除之后,再次使用它时,由原型链它会向上查找这个方法,即Object的toString(),也便将Object上的toString()方法作用在数组上,得出其数据类型[object Array]

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:ES6之 Map 和 Set
下一篇:浅谈 HTTP
相关文章

 发表评论

暂时没有评论,来抢沙发吧~