判断js变量的数据类型

数据类型

  • 基本数据类型: Null、Undefined、Number、String、Boolean、Symbol(ES6新增)。
    1. 简单的数据段,值不可变;
    2. 存在栈中 ,占据的空间大小固定;
    3. 直接按值存放,直接访问。
  • 引用数据类型:Object。
    1. 值可变,可动态地添加属性;
    2. 引用地址存在栈中,引用值存在堆内存,引用地址在栈中占据的空间大小固定,引用值的大小会改变;
    3. 按引用访问;

栈内存一般存储大小已知或有范围上限的变量,由系统分配空间;堆内存一般存储大小未知的变量,由代码分配空间。因此null代表空指针,使用typeof检测类型的时候,结果是“object”,但它存放在栈中,且不是以Object为原型创建出来的。

数据类型检测

  1. typeof

返回一个字符串,表示未经计算的操作数的类型。能够检测出除null之外的基本数据类型,对于object,只能检测出function。

类型结果
Undefinedundefined
Nullobject
Numbernumber
Booleanboolean
Stringstring
Symbolsymbol
Function对象function
其他对象object

例:

typeof 1; //"number"

typeof undefined; //"undefined"

typeof true; //"boolean"

typeof '123'; //"string"

typeof Symbol(42); //"symbol"

typeof function(){}; //"function"

typeof []; //"object"

typeof {}; //"object"

typeof null; //"object"
  1. instanceof

测试构造函数的prototype属性是否出现在对象的原型链中的任何位置。

  • 基本数据类型判断无效。由于基本数据类型的创建不会调用Object构造函数,没有__proto__(原型链)指向 Object.prototype(原型对象),因此需要实例方式创建的变量才有效。而对象在字面创建时,Js 引擎会解析并把这个对象的 __proto__ 指向 Object.prototype,因此对象的字面创建有效。
  • 出现在对象的原型链中的任何位置,检测结果都为true,因此既能判断是否是直接类的实例,也能判断时候是父类的实例。
  • 不能检测 null 和 undefined

例:

/** 基本数据类型与对象实例 **/

1 instanceof Number; // false,无效

new Number(1) instanceof Number; // true,typeof new Number(1) 为object

{} instanceof Object; // 报错:Uncaught SyntaxError: Unexpected token instanceof。原因是{}被解析为块语句,而不是对象。

({}) instanceof Object; // true

function(){} instanceof Object; // 报错:Function statements require a function name。原因是{}被解析为函数声明,而不是对象。

(function(){}) instanceof Object; // true



/** 原型链任何位置 **/

[] instanceof Array; // true

[] instanceof Object; //true



/** 其他对象检测 **/

new Date() instanceof Date; // true

new RegExp() instanceof RegExp;  // true
...
  1. constructor

`constructor是用来初始化对象,指向创建当前对象的构造函数,因此能够判断实例对象由哪个构造函数创建出来的。

  • 与instanceof 相比,constructor较为不稳定。因为构造函数的prototype(原型对象)被重写会影响constructor,而不影响instanceof的判断。
  • 能够检测基本数据类型(null与undefined除外 )
/** constructor 、 __proto__和 prototype 的关系 **/

function Person(){};

var person = new Person();

person.constructor === Person; //true,person对象的构造函数是Person函数

person.__proto__ === Person.prototype; //true,person对象的原型链指向Person的原型对象

Person.prototype.constructor === Person; //true,Person的原型对象的构造函数是它本身

person.__proto__.__proto__ === Object.prototype; //true

person.__proto__.__proto__.constructor === Object; //true

person.__proto__.__proto__.__proto__ === null; //true



/** 构造函数的prototype被重写的影响 **/

function Person(){};

var person1 = new Person();

Person.prototype = {
	name: '张三',
	age: 18,
}; //constructor被覆盖,消失了

var person2 = new Person();

person1.constructor === Person; //true

person2.constructor === Person; //false

person2.constructor === Object; //true,继承关系,顺着原型链往上一级找父对象的构造函数

person1 instanceof Person; //true

person2 instanceof Person; //true



/** 基本数据类型的检测 **/

var a = 1;

a.constructor === Number; //true

(1).constructor === Number; // true,对于数字需要加上(),否则小数点会解析错误
  1. Object.prototype.toString.call()

任何对象都有toString()方法,调用时返回格式"[object type]",type为对象的类型,任何数据类型的判断都可以通过Function.prototype.call的形式,即 Object.prototype.toString.call()来判断,传递要检查的对象作为第一个参数 。但是它不能检测非原生构造函数的构造函数名

类型结果
Undefined[object Undefined]
Null[object Null]
Number[object Number ]
Boolean[object Boolean]
String[object String]
Symbol[object Symbol]
Function[object Function]
Array[object Array]
Date[object Date]
RegExp[object RegExp]
Error[object Error]
document[object HTMLDocument]
Window[object Window]
非原生构造函数[object Object]
/** 各数据类型的判断**/
Object.prototype.toString.call(1); //[object Number]

Object.prototype.toString.call("1"); //[object String]

Object.prototype.toString.call(true); //[object Boolean]

Object.prototype.toString.call(null); //[object Null]

Object.prototype.toString.call(undefined); //[object Undefined]

Object.prototype.toString.call(Symbol(0)); //[object Symbol]

Object.prototype.toString.call({}); //[object Object]

Object.prototype.toString.call([]) ; // [object Array]

Object.prototype.toString.call(new Function()); //[object Function]

Object.prototype.toString.call(new Date()); //[object Date]

Object.prototype.toString.call(new RegExp()) ; // [object RegExp]

Object.prototype.toString.call(new Error()) ; // [object Error]

Object.prototype.toString.call(document) ; // [object HTMLDocument]

Object.prototype.toString.call(window) ; //[object Window] 



/** 非原生构造函数判断 **/

function Person(){};

var person = new Person();

Object.prototype.toString.call(person); //[object Object]

用Object.prototype.toString.call()封装一个判断类型的方法,如下:

function type(value){
	var typeName = Object.prototype.toString.call(value);
	return typeName.match(/(?<= )\b[a-zA-Z]*\b/)[0].toLocaleLowerCase();
}

type(); //undefined
type(null); //null
type(1); //number
type(true); //boolean
type({}); //object
type([]); //array
type(new Date()); //date
type(new function(){}); //function

参考文章:
JS基本数据类型和引用数据类型的区别及深浅拷贝
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
js数据类型的检测总结,附面试题–封装一个函数,输入任意,输出他的类型

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值