JavaScript基本类型数据都是直接按值存储在栈中的(Undefined、Null、不是new出来的布尔、数字和字符串),每种类型的数据占用的内存空间的大小是肯定的,并由系统自动分配和自动释放。这样带来的好处就是,内存能够及时获得回收,相对于堆来讲 ,更加容易管理内存空间。javascript
JavaScript引用类型数据被存储于堆中 (如对象、数组、函数等,它们是经过拷贝和new出来的)。其实,说存储于堆中,也不太准确,由于,引用类型的数据的地址指针是存储于栈中的,当咱们想要访问引用类型的值的时候,须要先从栈中得到对象的地址指针,而后,在经过地址指针找到堆中的所须要的数据。java
Symbol表示独一无二的值(须要注意的是经过 Symbol()方法建立值的时候不能使用 new 操做符,缘由是经过 new 实例化的结果是一个 object 对象,而不是原始类型的 symbol)
数组
const opt1 = Symbol('key');
const opt2 = Symbol('key');
const obj = {
[opt1]: 'value',
[opt2]: 'value',
}
// obj:{Symbol(key): "value", Symbol(key): "value"}
复制代码
// a.js
const privateKey = Symbol('key')
class myClass{
constructor(){
this.name = 'test'
// 由于Symbol独一无二的特性,此处的属性只能在a.js中被访问,
// 新建出来的实例也没法访问该属性,本质上是没法访问privateKey。
this[privateKey] = 'strange'
}
}
复制代码
如 String、Number、Boolean、Object、Function、Array、Date、RegExp、Error。实际上这些是一些内置函数,这些内置函数能够当作构造函数来使用,从而建立一个对应子类型的新对象。安全
具体不展开,详见 juejin.cn/post/684490…markdown
undefined的字面意思是:未定义的值。在试图读取未定义或者定义了未赋值的变量时会返回。数据结构
null的字面意思是:空值。在内存中能够表示为栈中的指针地址没有指向堆中的内存对象。(在JS最初的实现中,中的值是由一个表示类型的标签和实际数据值表示的,对象的类型标签是0。因为null表明的是空指针0x00,所以,null的类型标签也成为了 0,typeof null就错误的返回了"object")函数
判断数组:Object.prototype.toString.call(new Array()) === '[object Array]'post
缘由:JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。1位用来表示符号位,11位用来表示指数,52位表示尾数。ui
由于在计算机最底层,数值的运算和操做都是采用二进制实现的,因此计算机没有办法精确表示浮点数,而只能用二进制近似相等的去表示浮点数的小数部分。this
0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
0.2 >> 0.0011 0011 0011 0011…(0011无限循环)
0.1+0.2 = 0.01001100110011001100110011001100110011001100110011001110
转十进制0.30000000000000004
复制代码
当进行计算或其余操做时时,四舍五入(逢1进,逢0舍)将会致使最终的运算结果存在误差。
而大整数也存在一样的问题,由于表示尾数的尾数只有52位,所以 JS 中能精准表示的最大整数是 Math.pow(2, 53),即十进制9007199254740992。(ES2015的BigInt就是用来解决大数问题)
能够引入Math.js等一些专门处理此问题的三方库来解决精度丢失。