出處:JavaScript高級程序設計(第三版)第四章——變量、做用域和內存問題git
JS的方法參數是按值傳遞
的github
ES變量分爲兩種數據類型
的值:基本類型和引用類型函數
基本類型的值在申請內存時是固定大小,因此保存在棧內存
,故在複製基本類型變量時也是在棧內存中新開闢一分內存空間進行存儲ui
而引用類型變量的值大小不固定,且可任意改動,引用類型變量的本質是指向某一塊內存區域的指針變量,故引用類型變量存儲在內存自由分配的堆內存
中,在對引用變量做直接複製(從新賦值)時也只是將新的變量指向相同的一片內存區域(即兩個指針指向同一片堆內存空間)spa
引用類型的值是存放在內存中的對象
,但因爲JS語言不容許直接訪問內存
中的位置(即不能直接操做對象的內存空間),故操做對象時實際是在操做對象的引用
,而不是直接操做實際的對象自己(即引用類型的值是按引用
訪問的,這個引用能夠理解爲對象的句柄)設計
不少語言對於字符串是以對象形式進行表示,故爲引用類型變量,但ES不是指針
ES中全部函數(方法)的參數都是按值傳遞
的,即調用一個方法時,是將調用該方法時傳入該方法的參數的值
複製給函數內部的參數(將實參的值複製給形參)code
JS在訪問變量時有按值和按引用兩種方式,但參數只會按值傳遞對象
基本類型
的值被傳遞的值會被複制給一個局部變量
(這個局部變量就是形參,在ES中就是arguments對象的一個元素)blog
function addTen(num) {
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
// 看有沒有影響到原變量
alert(count);
alert(result)
複製代碼
執行結果
20
30
複製代碼
引用類型
的值JS會把被傳遞的值的地址複製給一個局部變量,由於複製的是地址,因此在函數執行時,函數形參在函數內部改變時會影響到函數外部的該引用變量的值,由於兩個地址指向同一片內存區域,但在函數執行結束,函數內部的局部變量被銷燬,影響即會消失
function setName(obj) {
obj.name = 'tom';
}
var person = new Object();
setName(person);
// 當把person傳遞給setName時,obj和person都指向相同的內存,因此對obj所指向的內存區域修改會影響到person
alert(person.name);
複製代碼
執行結果
tom
複製代碼
由於person指向的對象在堆內存中只存在一個,而且是全局對象
function setName(obj) {
obj.name = 'tom';
obj = new Object();
obj.name = 'jerry';
}
var person = new Object();
setName(person);
// 當把person傳遞給setName時,obj和person都指向相同的內存,因此對obj所指向的內存區域修改會影響到person
alert(person.name);
複製代碼
執行結果
tom
複製代碼
函數內部從新生成的對象obj,並對其新賦值jerry並無改變函數外部person對應的屬性值
若是向引用類型參數賦值是按引用賦值,那麼person的name應該變爲jerry,由於假設形參obj拿到的是person的引用,而不是person引用的值,那麼當函數內部生成新對象,並對obj進行從新指向時,形參obj的指向改變,外部的person的指向也應該改變,可是結果證實alert(person.name)顯示的依舊是tom,因此即便函數參數是引用類型,也是按值傳遞
而實際上在函數內部重寫obj時,這個變量引用的是一個局部對象變量
,該局部對象會在函數執行完畢
之時銷燬
原文自 我的github博客,歡迎star