说到 JavaScript 的基础知识,那肯定首当其冲的就是 基础类型 和 引用类型 了。
两种类型
JavaScript 中变量有两种不同类型的值:基本类型、引用类型。
基础类型保存在 栈内存 中,在按值访问,操作的是他们实际保存的值。
引用类型保存在 堆内存 中,但js不允许直接访问内存,所以在操作的时候,实际操作的是 对象的引用。

基础类型 主要有:字符串string
、数值number
、布尔值boolean
、null
、undefined
以及ES6中的symbol
(独一无二的值),加上现在最新的 BigInt
引用类型 主要有:对象object
、数组array
、正则 regExp
、函数function
、日期date
以及 特殊的基本包装类型(String、Number、Boolean
)、单体内置对象(Math
)等。
1 | // 基础类型 |
两种类型的复制
基本类型的复制
复制时,会在栈内存中创建一个新的值,然后把值复制到新分配的位置。

1 | // 基本类型的复制 |
引用类型的复制
复制的是存储在栈内存中的 指针,将 指针 复制到栈中新分配的位置,这个 指针副本 与 原指针 都指向存储在堆中的 同一个对象。由于同指向一个对象,所以当其中一个变量改变时,也将会影响另一个变量。

1 | // 引用类型的复制 |
tip
new String('abc')
属于引用类型,不等于'abc'
1
console.log(new String('abc')=== 'abc') // false
这是因为 String
只是一个 string
的对象封装类型,经过 new
操作符得出来的属于对象的实例。
- 使用
const
声明的对象,可以修改其属性1
2const a = {}
a.b = 123 // 不报错
这是因为 const对象对应的堆内存指向是不变的,但是堆内存中的数据本身的大小或者属性是可变的。而对于const定义的基础变量而言,这个值就相当于const对象的指针,是不可变。
如何判断类型
typeof
typeof
操作符是检测基本类型的最佳工具。
1 | console.log('字符串:',typeof 'abc') // 字符串: string |
可以发现,typeof
并不能完全区分出 null、object、array、regexp、date
等,得到的值都是 object
。
在 Javascript 语言中,typeof null === 'object'
。这样就会错误的认为 null
是一个对象。实际上这只是一个无法修复的bug。可以看这里
在《JavaScript高级程序设计》中这样解释:“因为特殊值null被认为是一个空对象的引用”。
而经过 typeof
测试,object、array、regexp、date
等 也都得出了 object
,这是因为所有的引用类型,在堆中都是对象,其实都是基于Object
实例进行的一种扩展。
至于 typeof function (){}
为什么是 function
, 在《JavaScript权威指南》中function
被看做是object
基本数据类型的一种特殊对象,《JavaScript高级程序设计》也把函数视为对象,而不是一种基本数据类型。
1 | var fn = function () { }; |
instanceof
instanceof
检测值是不是一个构造函数的实例。
1 | // 常规用法 |
经过实验,也可以得出,当使用 instanceof
检测基本类型时候,只会返回false
。
但是当使用 instanceof
检测frame的数组时,会出现问题。所以 Array.isArray()
应运而生。
1 | <html> |
constructor
如下:
1 | var a = 123 |
(…待更新)
toString
其实是使用Object.prototype.toString()
方法来检测数据类型。这个方法非常通用。
当然,也可以使用Reflect
,更加简洁。
1 | console.log(Object.prototype.toString.call(new Boolean(1))) // "[object Boolean]" |