JavaScript 判断数据类型的方法

Posted 猎人在吃肉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 判断数据类型的方法相关的知识,希望对你有一定的参考价值。

文章目录

1、javascript 中的数据类型

在 ECMAScript 规范中,共定义了 7 种数据类型,分为 基本类型 和 引用类型 两大类,如下所示:

基本类型:String、Number、Boolean、Symbol、Undefined、Null

引用类型:Object、Function 、Array、RegExp、Date

基本类型 ,也称为 简单类型,由于其占据空间固定,是简单的数据段,为了便于提升变量查询速度,将其存储在栈中,即按值访问。

引用类型 ,也称为 复杂类型,由于其值的大小会改变,所以不能将其存放在栈中,否则会降低变量查询速度,因此,其值存储在堆(heap)中,而存储在变量处的值,是一个指针,指向存储对象的内存处,即按址访问。

引用类型除 Object 外,还包括 Function 、Array、RegExp、Date 等等。

2、typeof 返回 变量的数据类型

typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。

返回的结果用该类型的字符串(全小写字母)形式表示,共 7 种。

numbe、stringr、boolean、undefinedfunction、object、symbol 等。

示例:

let obj=
    name:'dawn',
    age:21
;

let myFun = function() 
    console.log('我是 function 类型');
;

console.log(typeof myFun);      //function
console.log(typeof 1);       //number
console.log(typeof 'abc');   //string
console.log(typeof true);    //boolean
console.log(typeof undefined);  //undefined

// 下面这此,typeof 只有测出为 object,不能进一步判断它们的类型
console.log(typeof obj);          // object
console.log(typeof null);            //object ,无法准确测出是 null
console.log(typeof (new Date) );   //object  ,无法准确测出是 日期类型
console.log(typeof [1,2,3]);        //object ,无法准确测出是 数组
console.log(typeof (new RegExp()));  //object ,无法准确测出是 RegExp类型

说明:

  • typeof 可以准确测试出 number、string、boolean、undefined、function, 共5种数据类型。

  • 对象、null、数组、Date、Array数组等类型, typeof 只能测出为object,不能进一步判断它们的类型。

总结:

  • 对于基本类型,除 null 以外,均可以返回正确的结果。
  • 对于引用类型,除 function 以外,一律返回 object 类型。
  • 对于 null ,返回 object 类型。
  • 对于 function 返回 function 类型。

3、instanceof :复杂数据类型的判断

obj instanceof Object :左边是 要判断的内容,右边是类型,判断 obj 是否为 Object 的实例 。

instanceof 注意事项:

  • 只能用来判断 复杂数据类型 ,因为 instanceof 是用于检测构造函数(右边)的 prototype 属性是否出现在某个实例对象(左边)的原型链上。

  • 基本数据类型,不能用 instanceof 判断类型;

  • 基本数据包装类创建的 对象 可以用 instanceof 判断;

  • undefined 和 null 没有构造函数,所以使用 instanceof 会报错;

例子:

3.1、instanceof 原理分析(初学者跳过)

instanceof 检测的是 原型,我们用一段伪代码来模拟其内部执行过程:

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

从上述过程可以看出,当 A 的 proto 指向 B 的 prototype 时,就认为 A 就是 B 的实例。

我们再来看几个例子,

console.log([] instanceof Array); // true
console.log( instanceof Object);// true
console.log(new Date() instanceof Date); // true
 
function Person();
console.log(new Person() instanceof Person); // true
//上面的4种判断为true,应该都能理解


//下面这3个判断也为true, 大家可能会疑问
console.log([] instanceof Object); // true
console.log(new Date() instanceof Object);// true
console.log(new Person instanceof Object);// true

上面的例子中, instanceof 能够判断出 [ ] 是Array的实例,但它认为 [ ] 也是Object的实例,为什么呢?

我们来分析一下 [ ]、Array、Object 三者之间的关系:

通过上面的图 ,instanceof 能够判断出 [ ].__proto__ 指向 Array.prototype

Array.prototype.__proto__ 又指向 Object.prototype

最终, Object.prototype.__proto__ 指向了 null ,标志着原型链的结束。

因此,[]、Array、Object 就在内部形成了一条原型链。

instanceof 操作符的问题在于,它假定只有一个全局执行环境。如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[0].Array;
var arr = new xArray(1,2,3); // [1,2,3]
console.log(arr instanceof Array); // false

针对数组的这个问题,ES5 提供了 Array.isArray() 方法 。该方法用以确认某个对象本身是否为 Array 类型,而不区分该对象在哪个环境中创建。

if(Array.isArray(value))
   //对数组执行某些操作

Array.isArray() 本质上检测的是对象的 [[Class]] 值,

[[Class]] 是对象的一个内部属性,里面包含了对象的类型信息,其格式为 [object Xxx]Xxx 就是对应的具体类型 。

对于数组而言,[[Class]] 的值就是 [object Array]

3.2、使用示例

let arr=[1,2,3,4,5,6,7];
let obj=
    name:'zhangsan',
    age:21
;
let myfun=function() 
    console.log('我是 function 类型');
;;

console.log(arr instanceof Array);  //true
console.log(obj instanceof Object);  //true
console.log(myfun instanceof Function);  //true

console.log((new Date) instanceof Date);  //true

4、使用 Object.prototype.toString.call (最准确的判断类型)

toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 , Xxx 就是对象的类型。

对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

从实例我们可以看出该方法能判断基本类型,也能判断 Array 和 Function。

对于Object对象:

实例可见,对于Object对象,可以直接使用 toString() 方法,对于其他内置对象,Object.prototype.toString.call() 方法都能准确的判断出其类型。

结论:

Object.prototype.toString.call() 方法是判断类型的最准确的方法!

4.1、例子

简化:

Object.prototype.toString.call(obj) 简化为 toString.call(obj)

示例:

let obj = 
    name: 'dawn',
    age: 21
;
let myfun = function () 
    console.log('我是 function 类型');
;

console.log(toString.call(obj));       // [object Object]
console.log(toString.call(myfun));   // [object Function]

console.log(toString.call(1));        // [object Number]
console.log(toString.call('Hello tomorrow')); // [object String ]
console.log(toString.call(true));     // [object Boolean]
console.log(toString.call(undefined));  // [object Undefined]

console.log(toString.call(new Date));  // [object Date]
console.log(toString.call(null));   // [object Null]
console.log(toString.call([1, 2, 3]));  // [object Array]

5、使用 constructor

5.1、原理分析(初学者跳过)

当一个函数 F 被定义时,JavaScript 引擎会为 F 添加 prototype 原型,然后再在 prototype 上添加一个 constructor 属性,并让其指向 F 的引用。如下所示:

当执行 var f = new F() 时,F 被当成了构造函数,fF 的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F

可以看出,F 利用原型对象上的 constructor 引用了自身,当 F 作为构造函数来创建对象时,原型上的 constructor 就被遗传到了新创建的对象上, 从原型链角度讲,构造函数 F 就是新对象的类型。这样做的意义是,让新对象在诞生以后,就具有可追溯的数据类型。

同样,JavaScript 中的内置对象在内部构建时也是这样做的:

5.2、细节问题(初学者跳过)

1、null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。

2、 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object 。

为什么变成了 Object?

因为 prototype 被重新赋值的是一个 , 是 new Object() 的字面量,因此 new Object() 会将 Object 原型上的 constructor 传递给 ,也就是 Object 本身。

因此,为了规范开发,在重写对象原型时一般都需要重新给 constructor 赋值,以保证对象实例的类型不被篡改。

5.3、使用例子

let arr = [1, 2, 3, 4, 5, 6, 7]
let obj = 
    name: 'dawn',
    age: 21
;
let fn = function () 
    console.log('我是 function 类型');
;

console.log((9).constructor === Number);     //true
console.log('hello'.constructor === String);  //true
console.log(true.constructor === Boolean);    //true
console.log(fn.constructor === Function);     //true
console.log((new Date).constructor === Date); //true
console.log(obj.constructor === Object);      //true
console.log([1, 2, 3].constructor === Array); //true

注意:

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

6、jQuery 中判断数据类型的方法

jQuery 提供了一系列工具方法,用来判断数据类型,以弥补 JavaScript 原生的 typeof 运算符的不足。

以下方法对参数进行判断,返回一个布尔值。

jQuery.isArray();       // 是否为数组
jQuery.isEmptyObject(); // 是否为空对象 (不含可枚举属性)。
jQuery.isFunction();    // 是否为函数
jQuery.isNumberic();    // 是否为数字
jQuery.isPlainObject(): // 是否为使用“”或“new Object”生成对象,而不是浏览器原生提供的对象。
jQuery.isWindow();      // 是否为window对象;
jQuery.isXMLDoc();      // 判断一个DOM节点是否处于XML文档中。

以上是关于JavaScript 判断数据类型的方法的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 判断数据类型的方法

JavaScript 判断数据类型的方法

JavaScript 判断数据类型的方法

javascript数据类型及数据类型判断的四种方法

java中用啥方法判断数据类型,就行 javascript中的 typeOf一样

关于JavaScript的变量的数据类型的判断方法