這是我參與8月更文挑戰的第7天,活動詳情查看:8月更文挑戰數組
ECMAScript中全部函數的參數都是按值傳遞的。這意味着函數外的值會被複制到函數內部的參數中,就像從一個變量複製到另外一個變量同樣。markdown
若是是原始值,那麼就跟原始值變量的複製
同樣,若是是引用值,那麼就跟引用值變量的複製
同樣.對不少開發者來講,這一塊可能會很很差理解,畢竟變量有按值和按引用訪問,而傳慘則只有按值傳遞。app
在按值傳遞參數時,值會被複制到一個局部變量(即一個命名參數,或者用ECMAScript的話說,就是argument對象中的一個槽位)。在按引用傳遞參數時,值在內存中的位置會被保存在一個局部變量,這意味着對本地變量的修改會反映到函數外部。(這在ECMAScript中是不可能的。)函數
來看下面這個例子:post
function addTen(num) {
num += 10
return num
}
let count = 20
const result = addTen(count)
console.log(count) // 20 沒有變化
console.log(result) // 30
複製代碼
這裏,函數addTen()有一個參數num
,它實際上是一個局部變量。在調用時,變量count
做爲參數傳入.count
的值是20,這個值被複制到參數num
以便在addTen()
內部使用。在函數內部,參數num
的值被加上了10,但這不會影響函數外部的原始變量count
。參數num
和變量count
互不干擾,它們只不過碰巧保存了同樣的值。若是num
是按引用傳遞的,那麼count
的值也會被修改成30.這個事實在使用數值這樣的原始值時是很是明顯的。可是,若是變量中傳遞的是對象,就沒那麼清楚了。ui
好比,再看這個例子:url
function setName(obj) {
obj.name = '何小生'
}
let person = new Object()
setName(person)
console.log(person.name) // '何小生'
複製代碼
這一次,咱們建立了一個對象,並把它保存在變量person
中。而後,這個對象被傳給setName()
方法,並被複制到參數obj
中。在函數內部,obj
和person
都指向了同一個對象。結果就是,即便對象是按值傳進函數的,obj
也會經過引用訪問對象。當函數內部給obj
設置了name
屬性時,函數外部的對象也會反映這個變化,由於obj
指向的對象保存在全局做用域的堆內存上。不少開發者錯誤地認爲,當在局部做用域中修改而變化反映到全局時,就意味着參數是按引用傳遞的。爲證實對象是按值傳遞的,咱們再來看看下面這個修改後的例子。 例子:spa
function setName(obj) {
obj.name = '何小生'
obj = new Object()
obj.name = '小生'
}
let person = new Object()
setName(person)
console.log(person.name) // '何小生'
複製代碼
這個例子先後惟一的變化就是setName()
中多了兩行代碼,將obj
從新定義爲一個有着不一樣name
的新對象。當person
傳入setName()
時,其name
屬性被設置爲何小生
。而後變量obj
被設置爲一個新對象且name
屬性被設置爲小生
。若是person
是按引用傳遞的,那麼person
應該自動將指針改成指向name
爲小生
的對象。但是,當咱們再次訪問person.name
時,它的值時何小生
。這代表函數中參數的值改變以後,原始的引用仍然沒變。當obj
在函數內部被重寫時,它變成了一個指向本地對象的指針。而那個本地對象在指向函數結束時就被銷燬了。3d
注意:ECMAScript中函數的參數就是局部變量指針
總結小例子:
//數組
function setArray(arr) {
arr[0] = 1;
var arr = new Array(); //這裏的地址改變了
arr[0] = 6;
return arr;
}
var lastArr = new Array();
lastArr[0] = 0;
var newArr = setArray(lastArr);
console.log(lastArr[0] + '|' + newArr[0]); // 1|6
//對象
function setNameAgain(obj) {
obj.name = 'aaa';
var obj = new Object(); // 若是是按引用傳遞的,此處傳參進來obj應該被從新引用新的內存單元
obj.name = 'ccc';
return obj;
}
var person = new Object();
person.name = 'bbb';
var newPerson = setNameAgain(person);
console.log(person.name + ' | ' + newPerson.name); //aaa | ccc
複製代碼
在向參數傳遞基本類型的時候,被傳遞的值會被複制給一個局部變量(arguments對象中的一個元素)。
在向參數傳遞引用類型的值時,會把這個值在內存中的地址複製給一個局部變量,所以這個局部變量的變化會反映在函數的外部!
重點時須要搞清楚引用類型的地址與指向地址的指針!!!
公衆號:
小何成長
,佛系更文,都是本身曾經踩過的坑或者是學到的東西有興趣的小夥伴歡迎關注我哦,我是:
何小玍。
你們一塊兒進步鴨