js中判断数据类型的方法


typeof 、instanceof、constructor、jQuery.type()
1. typeof——返回对应的数据类型。
作用:区分基本数据类型
语法:typeof(变量名)

例:

var str = "我是字符串";
var num = 666;
var obj = new Object();
var arr = [1,2,3];
var fn = function(){
console.log("函数")
}
typeof(str) //string
typeof(num) //number
typeof(obj) //object
typeof(arr) //object
typeof(fn) //function

问题:如果是引用类型(复杂数据类型:对象和数组),那么返回的都是Object,无法具体区分

2. instanceof——只适用于对象类型,不适用于简单类型的数据类型,返回boolean值
作用:1:识别对象类型;
2:判断一个对象是否属于某个构造函数的实例
语法:变量名 instanceof 数据类型 || 实例对象名 instaneof 构造函数

例1:只要是对象类型的都可以区分

arr instanceof Array //true
new Date() instanceof Date //true

例2:使用instanceof来检验F是否属于构造函数fn的实例

var F = new fn(); //实例化构造函数
F instanceof fn ; //true,说明F是属于fn的实例

问题:对于不同的构造函数,同一个实例都返回了true,如下F对Object同样返回了true

F instanceof Object //true

instanceof原理:左边是一个实例对象,右边是一个构造函数,instanceof会检查构造函数的原型对象prototype是否在左边对象的原型链上,有则返回true,否则返回false.
instanecof内部执行函数:

instanceof (A,B) = {
var L = A.__proto__;
var R = B.prototype;
if(L === R) {
//A的内部属性__proto__指向B的原型对象
return true;
}
return false;
}

那么我们来看下左边对象的原型链以及右边函数的原型对象上都发生了什么
F.__proto__===fn.prototype //true 实例化对象F的原型指向fn的原型对象
F.__proto__.proto__||fn.prototype.__proto__===Object.prototype //true fn的原型又指向Object的原型对象
Object.prototype.__proto__ //null

说明从F——fn——Object都在一条原型链上,其中fn和Object的prototype属性都存在于F所在的这条原型链上,所以,F针对于两个函数都返回了true

3.constructor——本身是prototype对象的一个属性,默认指向prototype属性所在的构造函数,此处我们用来判断数据类型。返回boolean值
作用:1.判断数据类型,包括数组、日期、对象等,可以区分清楚
语法:变量名.constructor === 数据类型

例:

str.constructor===String //true
num.constructor===Number //true
obj.constructor===Object //true
arr.constructor===Array //true
new Date().constructor===Date //true


4.jQuery.type()——称之为万能
作用:判断数据类型。PS.其判断的结果显示都是小写的字符串形式
语法:jQuery.type(变量名)

例:包括日期、正则、undefined、null等都是可以判断的

jQuery.type(str) //string
jQuery.type(num) //number
jQuery.type(arr) //array
jQuery.type(obj) //object
jQuery.type(fn) //funtion

Javascript 中的数据类型判断其实是一个JavaScript非常基础问题,但不论是日常实际编程过程中和还是面试时,这都是一个非常常见的问题。

很多人被问到如何判断一个变量数据类型这个问题时,大概都能回答上几种方法,但是一深入的问题各种判断方法的区别、优劣、局限、原理,却一时半会理不清楚了,所以就借这一篇文章,复习一下JavaScript中这个基础但很容易出错的问题。

 

所以一般来说, typeof 会使用在比较简单的场景, 一般用在你几乎可以确定数据是哪一类数据然后稍微加以区分的时候。

举个例子,比如你已经知道某个变量一定是JS的6种基本类型之一时,你可以用typeof加以区分;又比如你不需要知道明确的类型,你只是想判断一个变量是不是对象或数组,这个时候也可以用typeof val === 'object'来判断(当然你需要确保这个变量不是null)。

不得不吐槽一句,typeof null === 'object' 其实是JavaScript的一个bug,那么多个版本还一直不肯改过来......

instanceof

instanceof 其实适合用于判断自定义的类实例对象, 而不是用来判断原生的数据类型, 举个例子:

// a.html
<script> var a = [1,2,3]; </script> // main.html <iframe src="a.html"></iframe> <script> var frame = window.frames[0]; var a = frame.a; console.log(a instanceof Array); // false  console.log(a.contructor === Array); //false  console.log(a instanceof frame.Array); // true </script>

是什么原因导致上面的结果呢? 其实 iframe 之间不会共享原型链, 因为他们有独立的执行环境, 所以 frame a 中的数组 a 不会是本执行环境的实例对象. 通过特性嗅探同样不靠谱, 像通过 contructor

Sort, slice 等等的特有的数组(或者其他数据类型)方法或属性, 万一对象中也有 sort, slice 属性, 就会发生误判. 所以最靠谱的方法是使用 Object.prototype.toString 方法.

Object.prototype.toString

在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。
需要注意的是,但是它不能检测非原生构造函数的构造函数名。

function foo(){}; Object.prototype.toString.call(1); '[object Number]' Object.prototype.toString.call(NaN); '[object Number]' Object.prototype.toString.call('1'); '[object String]' Object.prototype.toString.call(true); '[object Boolean]' Object.prototype.toString.call(undefined); '[object Undefined]' Object.prototype.toString.call(null); '[object Null]' Object.prototype.toString.call(Symbol());'[object Symbol]' Object.prototype.toString.call(foo); '[object Function]' Object.prototype.toString.call([1,2,3]); '[object Array]' Object.prototype.toString.call({});'[object Object]' 

从上面的例子可以看到,Object.prototype.toString 方法能有效弥补typeof不能很好区分数组、对象和函数的短板。

每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。

Object.prototype.toString 的原理是当调用的时候, 就取值内部的 [[Class]] 属性值, 然后拼接成 '[object ' + [[Class]] + ']' 这样的字符串并返回. 然后我们使用 call 方法来获取任何值的数据类型.

constructor

console.log(bool.constructor === Boolean);// true  console.log(num.constructor === Number);// true  console.log(str.constructor === String);// true  console.log(arr.constructor === Array);// true  console.log(obj.constructor === Object);// true  console.log(fun.constructor === Function);// true  console.log(Symbol.constructor === Symbol);// true  console.log(haoxl.constructor === Student);// false  console.log(haoxl.constructor === Person);// true 

undefined和null没有contructor属性

constructor不能判断undefined和null,并且使用它是不安全的,因为contructor的指向是可以改变的

有用的数据类型判断函数

Array.isArray()
用于确定传递的值是否是一个Array。如果对象是Array,则返回true,否则为false。

Array.isArray([1, 2, 3]); // true Array.isArray({foo: 123}); // false Array.isArray("foobar"); // false Array.isArray(undefined); // false 

isNaN()和Number.isNaN
isNaN()函数用来确定一个值是否为 NaN。
注:isNaN函数内包含一些非常有趣的规则;
你也可以使用 ECMAScript 2015 中定义的Number.isNaN()来判断。

与 JavaScript 中其他的值不同, NaN不能通过相等操作符(== 和 ===)来判断 ,因为 NaN == NaN 和 NaN === NaN 都会返回 false。 因此,isNaN 就很有必要了。

isNaN(NaN); // true 

OK, 成功了,看似很完美,但是接着看以下例子

isNaN('A String'); // true  isNaN(undefined); // true  isNaN({}); // true 

会发现,很明显不是 NaN 的 value 也被误判成 NaN 了。

这个BUG已经存在了20年,从JavaScript最开始就一直存在。很明显当初的设计者,在设计isNaN()的时候,局限了在 "Not a Number" 这一字面意思上了:只要不是number就会返回 true。

于是 ES6 为了弥补这一BUG(而不是修正,因为isNaN存在时间太长,有可能很多功能都是基于这个BUG之上的)引入了 Number.isNaN().

Number.isNaN(NaN); // true  Number.isNaN('A String'); // false  Number.isNaN(undefined); // false  Number.isNaN({}); // false 

没有ES6的情况下,可以采用以下polyfill

if (!Number.isNaN) { Number.isNaN = function(n) { return ( typeof n === "number" && window.isNaN( n ) ); }; } 

判断是否是 DOM 元素

在实际项目里面, 有时或许我们需要判断是否是 DOM 元素对象, 那么在判断的时候利用的是 DOM 对象特有的 nodeType 属性:

isElement: function(obj){ return !!(obj && obj.nodeType === 1); } 

判断是否是对象

isObject: function(obj){ var type = typeof obj; return type === 'function' || typeof === 'object' && obj !== null; } 

这里的对象是狭义的, 是通常所指的 key-value 型的集合, 或者是 function 函数并且不为 null.

判断是否是 arguments 对象

判断一个对象是不是 arguments 对象可以通过 Object.prototype.toString 来判断, 但是低版本的浏览器不支持, 他们返回的是 [object Object], 所以需要兼容:

isArguments: function(obj){ return Object.prototype.toString.call(obj) === '[object Arguments]' || (obj != null && Object.hasOwnProperty.call(obj, 'callee')); } 

兼容做法原理是通过对象的 hasOwnProperty 方法来判断对象是否拥有 callee 属性从而判断是不是 arguments 对象.

 


总结:
typeof()——判断简单的数据类型,无法菊粉复杂数据类型,例如像Object和Array返回的都是Object
instanceof ——仅适用于对象来区分数据类型。同时还可以判断某个实例是否是某个构造函数的实例,但是会出现对应多个构造函数的情况
constructor——判断所有的数据类型。当然他的本质是盘算prototyep属性所在的函数的
jQuery.type()——判断所有的数据类型。
原文链接:https://blog.csdn.net/baidu_41604826/article/details/89710303


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM