1.数据类型分为七种,Number,String,Boolean,Object,Undefined,Null,symbol(ES6);除了Object以外,其余都是基本类型的值。Object为复合类型的值。因为它是以上数据类型的集合。
这是一个Object:{a:1,b:'字符串',c:null,d:undefined,e:fun(),f:[].g:{}},由此可见,它可以包含所有的数据类型作为它的属性,而基本类型的值是单一的。
2.Object与其他类型的值的存储方式是不一样的,我们知道JS的内存分为代码区和数据区,数据区又分 Stack(栈)和Heap(堆)。
基本类型的值,他们会存储在栈中,Object则会存储在堆中。如果你声明一个变量,你把基本类型的值赋值给它,如果调用这个变量,那么就会去Stack中寻找这个值。如果你赋值变量一个Object,你调用这个变量的时候,在stack中是找不到这个Object的,你只会找到这个Object的地址,这个地址指向这个Object的位置,最终会在Heap中找到这个Object。
3.由于存储方式不一样,会有深拷贝与浅拷贝的区别。
深拷贝:基本类型的值,赋值的时候就是深拷贝,比如:
var a = 1;
var b = a;//b=1
b = 2;//a的值还是1
以上可见,变量b的重新赋值,并没有改变a的值,这就是一个深拷贝,因为在Stack中,每个变量的值与这个变量都是一一对应的,并不会出现两个变量共享一个值的的事情,所以上面的操作是覆盖了Stack中变量b的值,所以对a没影响。
浅拷贝:对下例Object属性的覆盖,就是一个浅拷贝:
var a = {name: 'wang'}
var b = a
b.name = 'b'
a.name === 'b' // true
以上可见,改变对象b的name属性,对象a的name属性也随之而变,这就是一个浅拷贝。我们一步步看,首先声明对象a,a的值并不是存在栈中,存在栈中的是一个地址,这个地址指向这个存储在堆中的对象。然后把a赋值给了变量b,这时候其实是把a在栈中的那个地址拷贝给了b,这个时候a,b存在栈中的地址都指向同一个存储在堆中的对象,这个对象是唯一的,所以给b.name重新赋值之后,a,name的值也就跟着发生了改变。