JS数据类型及常见转换规则

数据类型

JS中的数据类型主要分为两大类:原始类型引用类型。常见的数据类型如下图所示:

JS数据类型及常见转换规则

原始数据类型存在栈中,引用类型在栈中存的是一个引用地址,这个地址指向的是堆中的一个数据对象。需要注意的是null在这里我们算在原始类型里面,但是你用typeof的时候会发现他是object,原因是就算他是一个对象,那他应该在栈中存一个引用地址,但是他是一个空对象,所以这个地址为空,也就是不对应堆中的任意一个数据,他在堆中没有数据,只存在于栈中,所以这里算为了原始类型。引用类型其实主要就是ObjectArrayFunction这些其实也都是Object派生出来的。

原始类型

原始类型的值无法更改,要更改只能重新赋值,原始类型的比较就是比较值,值相等,他们就相等

引用类型

引用类型的值是可以修改的,修改后引用地址并没有变化,变化的是堆中的数据。

引用类型的比较是比较他们的索引地址,而不是他们的值。

要想让他们相等,得直接将b赋值为a,这样他们的引用地址一样,就是相等的。

类型转换

隐式类型转换

转为字符串

经常出现在+运算中,并且其中有一个操作数不是数值类型

let s = 4 + 'px' + 5;
console.log(s);   // 4px5

s = 123e-2 + 'a';  
console.log(s);   // 1.23a
复制代码

转为数值

经常出现在数学运算中,表示连接字符串的+运算除外

let s = 'abc';
console.log(+s, -s); // NaN, NaN

s = ' 123 ';
console.log(+s, -s); // 123 -123

s = new Date();
console.log(+s, -s);  // 1588675647421 -1588675647421   (这个操作相当于取毫秒数)

转为bool的场景

经常出现在if或者逻辑运算中

let s = 'abc';
if(s) {
  console.log(s);  // abc
}

console.log(!!s);  // true

下面的值在进行bool转换时会转换为false,除此以外都是true:

  1. 0
  2. NaN
  3. ''(空字符串)
  4. null
  5. undefined

==运算符

当我们使用==进行比较时,如果两边的类型不同,JS会进行类型转换,然后再比较,===则不会进行类型转换,如果===两边的数据类型不同,直接返回false

JS数据类型及常见转换规则JS数据类型及常见转换规则JS数据类型及常见转换规则JS数据类型及常见转换规则

类型检测

类型检测是我们经常遇到的问题,面试时也经常问到各种类型检测的方法,下面是几种常用的类型检测的方法。

typeof

做类型检测最常用的就是typeof了:

let a;
typeof a;   // undefined

let b = true;
typeof b;   // boolean

let c = 123;
typeof c;   // number

let d = 'abc';
typeof d;   // string

let e = () => {};
typeof e;   // function

let f = {};
typeof f;   // object

let g = Symbol();
typeof g;   // symbol

instanceof

typeof最简单,但是他只能判断基本的类型,如果是对象的话,没法判断具体是哪个对象。instanceof可以检测一个对象是不是某个类的实例,这种检测其实基于面向对象和原型链的,更多关于instanceof原理的可以看这篇文章。下面来看个例子:

let a = new Date();
a instanceof Date;  // true
let arr=[2]
arr instanceof Array //true

constructor

constructor的原理其实跟前面的instanceof有点像,也是基于面向对象和原型链的。一个对象如果是一个类的实例的话,那他原型上的constructor其实也就指向了这个类,我们可以通过判断他的constructor来判断他是不是某个类的实例。

Object.prototype.toString.call

Object.prototype.toString.call是比较准确的,可以用来判断原生对象具体是哪个类型:

Object.prototype.toString.call(new Array());   // [object Array]
Object.prototype.toString.call(new Date());    // [object Date]
复制代码

这个方法返回的是[object XXX],这个XXX是对应的构造函数名字。但是他只能检测原生对象,对于自定义类型是没有用的:

function a() {}
let b = new a();

Object.prototype.toString.call(b);   // [object Object]
JS数据类型及常见转换规则