基本数据类型和引用数据类型
1. 基本数据类型
ES5里面有五大基本数据类型:string、number、boolean、undefined、null
ES6里面又新增了一个基本数据类型:Symbol,表示独一无二的值。Symbol数据类型的值是通过symbol函数生成的,每个symbol函数都是独立的,拥有不同的返回值。
这些类型可以直接操作保存在变量中的实际值。
let obj1 = Symbol('a');
let obj2 = Symbol('b');
console.log(obj1); //Symbol(a)
console.log(obj2); //Symbol(b)
console.log( obj1 == obj2); //false
console.log(typeof obj1); //symbol
Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
Symbol的作用:
- 使用Symbol定义的变量不可以对外访问和修改
- 使用Symbol定义的变量不可以利用for循环等进行遍历
- Symbol函数前不能使用new命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。
2. 引用数据类型
Array、Function、Object…(在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象,这些都是引用数据类型)
3. 基本数据类型和引用数据类型的区别
- 声明变量时存储位置不同
基本数据类型:在声明之后被保存在栈中,因为基本数据类型的大小是固定的,所占用内存小,存放在栈中,方便在使用的时候进行快速查找。
引用数据类型:在声明之后被保存在堆中,因为引用数据类型占用内存空间大,且不固定,所以不能把它放在栈中,会降低变量查找的速度。但是可以将变量的地址存放在栈中,这样当想要查找某个变量的时候,就可以先在栈中查找该变量所对应的在堆中地址,找到地址后,就可以在堆中找到该变量了。
- 访问机制不同
由于基本数据类型和引用数据类型所存放的位置不同,所以导致其访问的机制也不同,存放在堆中变量不可以直接访问,需要先在栈中找到相应的地址,然后再根据地址在堆中进行查找,而基本数据类型的值则可以直接找到。
- 复制机制不同
基本数据类型:在将一个保存着基本数据类型的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。
引用数据类型:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。
复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个指向这个对象的指针。
- 参数传递的方式不同
基本数据类型:只是把变量里的值传递给参数,之后参数和这个变量互不影响。
引用数据类型:传递的值是内存地址。
在面试的过程中,有被问到过var、let、const的区别,当说到const定义的值是不可以被改变的时候,面试官产生了疑问,问我为什么,定义一个数组,可以通过数组的一些方法改变变量的值嘛,我犹豫了,好像确实可以,但却说不出来为什么,现在终于搞懂了:
原来用const定义的基本数据类型确实不可以被修改,而定义的引用数据类型是可以被修改的,const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的。也就是说用const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。