一次性彻底明白javascript数据类型及判断方法

88 阅读4分钟

基本数据类型

存储在栈内存中,占据空间小、大小固定、读写速度快。基本数据类型变量存储的是值本身。

  1. undefined
  2. null
  3. Boolean
  4. Number
  5. String
  6. Symbol(es6新增)表示独一无二的值且不可变,一般用于对象的属性名。对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。
  7. BigInt(es2020新增)BigInt是一种新的数据类型,当整数值大于Number数据类型支持的范围时使用。这种数据类型允许我们安全地对大整数执行算术操作。JS中的Number无法精确表示非常大的整数,它会将非常大的整数四舍五入,JS中的Number类型只能安全地表示-9007199254740991(-(2^53 - 1))和9007199254740991(2^53 - 1),任何超出此范围的整数值都可能失去精度。

引用数据类型

存放在堆内存中,占据空间大、大小不固定、读写速度慢。引用数据类型变量存储的是一个指针(栈内存),该指针指向数据实体在堆中的地址。

  1. Object (Array、Function、Object等)

基础数据类型赋值

当把变量a赋值给变量b时,会直接把变量a的值复制一份,然后赋值给变量b,这时改变变量a或者变量b的值,不会改变另外一个变量的值。

let a = 18;
let b = a;
a = 20;
console.log(a); // 20
console.log(b); // 18

引用数据类型赋值

当把变量a赋值给变量b时,是把变量a的内存地址复制一份赋值给变量b。

  • 改变变量a所指向的堆内存中的数据时会让另一个变量b的值改变。
let a = {
  name: 'dyx'
};
let b = a;
a.name = 'douyaxing';
console.log(a); // { name: 'douyaxing' }
console.log(b); // { name: 'douyaxing' }
  • 直接改变变量a的指针指向时不会让另一个变量b的值改变。
let a = {
  name: 'dyx'
};
let b = a;
a = {
  name: 'douyaxing'
};
console.log(a); // { name: 'douyaxing' }
console.log(b); // { name: 'dyx' }

数据类型判断

typeof

  • typeof返回一个表示数据类型的字符串,返回结果包括string、number、boolean、symbol、undefined、object、function等7种数据类型。
  • typeof对于基本数据类型除了null都可以显示正确的类型,typeof对于引用数据类型除了函数会显示function其它都会显示object。
typeof '123';              // string 有效
typeof 1;                  // number 有效
typeof true;               // boolean 有效
typeof Symbol('1');        // symbol 有效
typeof undefined;          // undefined 有效
typeof null;               // object 无效
typeof {};                 // object 有效
typeof function() {};      // function 有效
typeof [];                 // object 无效
typeof new Date();         // object 无效
typeof new RegExp();       // object 无效

instanceof

  • instanceof用来判断A是否为B的实例,内部机制是检测构造函数的prototype属性是否出现在某个实例对象的原型链上。
  • 不能获取具体的数据类型。
  • instanceof可以正确的判断引用数据的类型,无法正确判断基本数据的类型。
'123' instanceof String;                // false 无效
1 instanceof Number;                    // false 无效
true instanceof Boolean;                // false 无效
Symbol('1') instanceof Symbol;          // false 无效
{} instanceof Object;                   // true 有效
function() {} instanceof Function;      // true 有效
[] instanceof Array;                    // true 有效
new Date() instanceof Date;             // true 有效
new RegExp() instanceof RegExp;         // true 有效

constructor

  • 当一个构造函数被定义时,构造函数会有原型对象prototype,原型对象上constructor属性指向构造函数。使用构造函数创建对象时,创建的对象继承了构造函数原型对象prototype。新创建的对象的constructor属性指向构造函数。
  • 不能获取具体的数据类型。
  • 除undefined、null两种数据类型外都可以判断正确的类型,undefined、null没有原生构造函数。
  • 当修改了构造函数原型对象的constructor属性值时,使用constructor判断数据类型就变得不可靠了。
('123').constructor === String;           // true
(1).constructor === Number;               // true
(true).constructor === Boolean;           // true
(Symbol('1')).constructor === Symbol;     // true            
({}).constructor === Object;              // true 
(function() {}).constructor === Function; // true 
([]).constructor === Array;               // true 
(new Date()).constructor === Date;        // true 
(new RegExp()).constructor === RegExp;    // true 

Object.prototype.toString.call()

  • 使用Object原型对象上的toString方法,toString方法返回运行时this指向的对象类型,返回的类型格式为[object,xxx],xxx是具体的数据类型。
  • 最准确的类型判断方法。适用所有的数据类型。
Object.prototype.toString.call('123');         // [object, String]
Object.prototype.toString.call(1);             // [object, Number]
Object.prototype.toString.call(true);          // [object, Boolean]
Object.prototype.toString.call(Symbol('1'));   // [object, Symbol]
Object.prototype.toString.call(undefined);     // [object, Undefined]
Object.prototype.toString.call(null);          // [object, Null]
Object.prototype.toString.call({});            // [object, Object]
Object.prototype.toString.call(function() {}); // [object, Function]
Object.prototype.toString.call([]);            // [object, Array]
Object.prototype.toString.call(new Date());    // [object, Date]
Object.prototype.toString.call(new RegExp());  // [object, RegExp]

// 通用的判断方法
const checkType = data => {
  const type = Object.prototype.toString.call(data); // 返回字符串类型的值
  // 截取代表真正数据类型部分
  return type.slice(8, -1);
}