一、在 javascript 中数据类型能够分为两类:
- 原始数据类型值 primitive type,如Undefined,Null,Boolean,Number,String。
- 援用类型值,也就是对象类型 Object type,如Object,Array,Function,Date等。
二、申明变量时不同的内存调配
- 原始值:存储在栈(stack)中的简略数据段,也就是说,它们的值间接存储在变量拜访的地位。这是因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域 – “栈”中。这样存储便于迅速查寻变量的值。
- 援用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。这是因为:援用值的大小会扭转,所以不能把它放在栈中,否则会升高变量查寻的速度。相同,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。
三、不同的内存分配机制也带来了不同的拜访机制
在javascript中是不容许间接拜访保留在“堆”内存中的对象的,所以在拜访一个对象时,首先失去的是这个对象在堆内存中的地址,而后再依照这个地址去取得这个对象中的值,这就是传说中的按援用拜访。而原始类型的值则是能够间接拜访到的。
1、复制变量时的不同
- 原始值:在将一个保留着原始值的变量复制给另一个变量时,会将原始值的正本赋值给新变量,尔后这两个变量是齐全独立的,他们只是领有雷同的value而已。
- 援用值:在将一个保留着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的扭转都会反映在另一个身上。(这里要了解的一点就是,复制对象时并不会在堆内存中新生成一个截然不同的对象,只是多了一个保留指向这个对象指针的变量罢了)
2.参数传递的不同
首先咱们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。然而为什么波及到原始类型与援用类型的值时依然有区别呢,还不就是因为内存调配时的差异。 (这个复制变量时遵循的机制齐全一样)
- 原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。
- 援用值:对象变量它外面的值是这个对象在堆内存中的内存地址,这一点你要时刻铭记在心!因而它传递的值也就是这个内存地址,这也就是为什么函数外部对这个参数的批改会体现在内部的起因了,因为它们都指向同一个对象呀。图示阐明:
所以,如果是按援用传递的话,是把第二格中的内容(也就是变量自身)整个传递进去(就不会有第四格的存在了)。但事实是变量把它外面的值传递(复制)给了参数,让这个参数也指向原对象。因而如果在函数外部给这个参数赋值另一个对象时,这个参数就会更改它的值为新对象的内存地址指向新的对象,但此时原来的变量依然指向原来的对象,这时候他们是互相独立的;但如果这个参数是扭转对象外部的属性的话,这个扭转会体现在内部,因为他们独特指向的这个对象被批改了呀!来看上面这个例子吧:(传说中的call by sharing)
var obj1 = { value:'花点工夫1' }; var obj2 = { value:'花点工夫2' }; function changeStuff(obj){ obj.value = '花点工夫3'; obj = obj2; return obj.value; } var foo = changeStuff(obj1); console.log(foo);// '花点工夫2' 参数obj指向了新的对象obj2 console.log(obj1.value);//'花点工夫3',形参obj和对象obj1指向了独特的内存地址,obj扭转后,堆(heap)内存中的对象扭转,因而obj1的值也产生了扭转。