1. 數據類型javascript
在 javascript 中數據類型能夠分爲兩類:java
原始數據類型值(primitive type),好比Undefined,Null,Boolean,Number,String。函數
引用類型值,也就是對象類型 Object type,好比Object,Array,Function,Date等。性能
聲明變量時不一樣的內存分配指針
原始值:存儲在棧(stack)中的簡單數據段,也就是說,它們的值直接存儲在變量訪問的位置。這是由於這些原始類型佔據的空間是固定的,因此可將他們存儲在較小的內存區域 – 棧中。這樣存儲便於迅速查尋變量的值。對象
引用值:存儲在堆(heap)中的對象,也就是說,存儲在變量處的值是一個指針(point),指向存儲對象的內存地址。這是由於:引用值的大小會改變,因此不能把它放在棧中,不然會下降變量查尋的速度。相反,放在變量的棧空間中的值是該對象存儲在堆中的地址。地址的大小是固定的,因此把它存儲在棧中對變量性能無任何負面影響。blog
2. 不一樣的內存分配機制也帶來了不一樣的訪問機制ip
在javascript中是不容許直接訪問保存在堆內存中的對象的,因此在訪問一個對象時,首先獲得的是這個對象在堆內存中的地址,而後再按照這個地址去得到這個對象中的值,這就是傳說中的按引用訪問。而原始類型的值則是能夠直接訪問到的。內存
3. 複製變量時的不一樣it
原始值:在將一個保存着原始值的變量複製給另外一個變量時,會將原始值的副本賦值給新變量,此後這兩個變量是徹底獨立的,他們只是擁有相同的value而已。
引用值:在將一個保存着對象內存地址的變量複製給另外一個變量時,會把這個內存地址賦值給新變量,也就是說這兩個變量都指向了堆內存中的同一個對象,他們中任何一個做出的改變都會反映在另外一個身上。(這裏要理解的一點就是,複製對象時並不會在堆內存中新生成一個如出一轍的對象,只是多了一個保存指向這個對象指針的變量罷了)
4. 參數傳遞的不一樣
首先咱們應該明確一點:ECMAScript中全部函數的參數都是按值來傳遞的。可是爲何涉及到原始類型與引用類型的值時仍然有區別呢,還不就是由於內存分配時的差異。 (我對比了一下,這裏和複製變量時遵循的機制徹底同樣的嘛,你能夠簡單地理解爲傳遞參數的時候,就是把實參複製給形參的過程)
按值傳遞(call by value):只是把變量裏的值傳遞給參數,以後參數和這個變量互不影響。
按引用傳遞(call by reference): 函數的形參接收實參的隱式引用,而再也不是副本。這意味着函數形參的值若是被修改,實參也會被修改。同時二者指向相同的值。
咱們先看一個C的例子來了解按值和引用傳遞的區別:
void Modify(int p, int * q)
{
p = 27; // 按值傳遞 - p是實參a的副本, 只有p被修改
*q = 27; // q是b的引用,q和b都被修改
}
int main()
{
int a = 1;
int b = 1;
Modify(a, &b); // a 按值傳遞, b 按引用傳遞,
// a 未變化, b 改變了
return(0);
}
按共享傳遞 call by sharing
對象變量它裏面的值是這個對象在堆內存中的內存地址,這一點你要時刻銘記在心!所以它傳遞的值也就是這個內存地址,這也就是爲何函數內部對這個參數的修改會體如今外部的緣由了,由於它們都指向同一個對象呀。調用函數傳參時,函數接受對象實參引用的副本(既不是按值傳遞的對象副本,也不是按引用傳遞的隱式引用)。 它和按引用傳遞的不一樣在於:在共享傳遞中對函數形參的賦值,不會影響實參的值。以下面例子中,不能夠經過修改形參o的值,來修改obj的值。
var obj = {x : 1};
function foo(o) {
o = 100;
}
foo(obj);
console.log(obj.x); // 仍然是1, obj並未被修改成100.
因此,若是是按引用傳遞的話,是把第二格中的內容(也就是變量自己)整個傳遞進去(就不會有第四格的存在了)。但事實是變量把它裏面的值傳遞(複製)給了參數,讓這個參數也指向原對象。所以若是在函數內部給這個參數賦值另外一個對象時,這個參數就會更改它的值爲新對象的內存地址指向新的對象,但此時原來的變量仍然指向原來的對象,這時候他們是相互獨立的;但若是這個參數是改變對象內部的屬性的話,這個改變會體如今外部,由於他們共同指向的這個對象被修改了呀!來看下面這個例子吧:(傳說中的call by sharing)
var obj1 = {
value:'111'
};
var obj2 = {
value:'222'
};
function changeStuff(obj){
obj.value = '333';
obj = obj2;
return obj.value;
}
var foo = changeStuff(obj1);
console.log(foo);// '222' 參數obj指向了新的對象obj2
console.log(obj1.value);//'333'
*obj1仍然指向原來的對象,之因此value改變了,
*是由於changeStuff裏的第一條語句,這個時候obj是指向obj1的 .
*再囉嗦一句,若是是按引用傳遞的話,這個時候obj1.value應該是等於'222'的