app开发者平台在数字化时代的重要性与发展趋势解析
575
2022-11-15
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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~