JavaScript中数据类型四种检测方式

JS中数据类型检测

检测宗旨

对一些不确定的值操作时,为了避免发生错误,最稳妥的方式是在操作之前要加一个数据类型判断,再根据相应类型来进行不同的操作。

比如回调函数

function fn(callBack) {
	callBack();
}

这个时候就要在callBack执行之前加一个是否为函数的判断,如果是再让函数执行
修改如下

function fn(callBack) {
	if(typeof callBack === 'function') {
		callBack();
	}
}

在检测一些引用数据类型的时候,我们更想知道这个对象是属于哪个类,比如想判断一个对象是否为数组,好去调用数组上的方法,而不是想判断这个对象是不是属于对象。因为数组的方法都是保存在数组的原型上,而不是在Object基类上。

检测方法

typeof

用法

typeof是一个操作符
在执行的时候可以typeof(要检测的对象)
也可以这样typeof 要检测的对象,因为typeof不是函数,因此()不是必需的,可以将检测的对象直接跟在typeof后面

检测范围

在JS中,能用typeof能检测出来的数据类型,最好使用typeof来检测
typeof是基本数据类型检测利器(但是不包括null);也可以检测是否为一个函数,但是在检测对象时,并不能为每个对象明确指出是属于哪一类,因为返回值都是object

示例

typeof 1;//'number'
typeof true;//'boolean'
typeof '';//'string'
typeof undefined;//'undefined'
typeof function (){};'function'

tips

typeof的返回值是一个字符串,有时候在浏览器里会把引号省略掉,但是可以用typeof去检测这个返回值,比如

typeof typeof 1;//'string'
//这行代码的意思是,用typeof去检测typeof 1的返回值,最终的返回值是string

因为这个也以引伸,如果两个及以上的typeof连用的话,那么输出的结果就是string

typeof null

null在JS中叫做空对象指针,因此可以理解为null为对象

而更专业的解释是

JS类型值是存在32 BIT 单元里,32位有1-3位表示TYPE TAG,其它位表示真实值 而表示object的标记位正好是低三位都是0 000: object. The data is a reference to an object. 而js 里的Null 是机器码NULL空指针, (0x00 is most platforms).所以空指针引用 加上 对象标记还是0,最终体现的类型还是object..

instanceof

用法

instanceof是一个操作符,返回值是一个布尔值
instanceof是检测引用数据类型,而不能检测基本数据类型

var arr = [];
arr instanceof Array;//true

但是只要是在原型链上出现过构造函数都会返回true,所以这个检测结果不很准确

arr instanceof Object;//true

constructor

constructor这个属性存在于构造函数的原型上,指向构造函数,对象可以通过__proto__在其所属类的原型上找到这个属性

var arr = [];
arr.constructor === Array;//true
arr.constructor === Object;//false
//因为arr通过原型链查找到的constructor指向了Array,所以跟Object判断就是错误滴

constructor是比较准确判断对象的所属类型的,但是如果有继承的话

function Fn() {

}
Fn.prototype = new Array();
var fn = new Fn();
console.log(fn.constructor === Array);
//fn是一个对象,但是它的构造函数指向Array竟然是true

因此这个方法要慎用

Object.prototype.toString.call()

在Object基本类定义的这个toString()方法,是用来检测数据类型的;
跟字符串、数字、布尔等原型上定义的toString()方法基本用法都是转换字符串的。

这对对数据检测应该是最准确的

console.log(Object.prototype.toString.call(1));//[object Number]
console.log(Object.prototype.toString.call(''));//[object String]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(null));// [object Null]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call([]));// [object Array]
console.log(Object.prototype.toString.call({}));// [object Object]
console.log(Object.prototype.toString.call(/^$/));//[object RegExp]
console.log(Object.prototype.toString.call((function () {})));//[object Function]

基本包装类型

JS是一门弱类型的语言,因此在定义变量时,一般都可以使用字面量方式和实例创建方式。
一般两种创建方式没有差别,但是涉及到基本数据类型中的number、string、boolean时就完成不一样。

例如

var a = 1;
var b = new Number(1);
typeof a;//'number'
typeof b;//'object'

因为字面创建基本数据类型的值时,并不会调用JS的内置构造函数,因此字面量创建的值就是基本数据类型,而不是实例(对象数据类型)。-->所以用instanceof检测基本数据类型时都会返回false

但是一个基本数据类型并不是对象,是不应该有属性的,但是给一个字符串添加一个属性时,也不会报错,在读取属性时,也什么也读取不到。

var str = 'chang';
str.name = 'joo';
console.log(str.name);//undefined

这是因为,在JS中有三种基本包装类型,Nmber,String,Boolean
例如一个字符串,当作对象去调用其原型上的方法时,JS会临时创建一个与其对应的基本包装类型的值,这个值是String的实例,调用方法,其实是这个实例在调用字符串的方法。

var str = 'chang';
str.split('');//代码执行到这行时,会临时创建与str等价的对象,去调用字符串的方法

这个临时创建的对象的生命周期,只有在调用方法的一瞬间,调用完成后就随即销毁了。因此上例在给字符串添加属性时不会报错,在读取时也读不到销毁的字符串,因此读取时返回undefined。

这样,在用constructor检测数据类型时

var str = 'chang';
str.constructor === String;//true

检测的其实是临时创建的基本包装类型的对象

原文地址:https://www.cnblogs.com/changzhenan/p/7120929.html