ECMAScript變量 - 傳遞參數 (高頻面試點)

這是我參與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中。在函數內部,objperson都指向了同一個對象。結果就是,即便對象是按值傳進函數的,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對象中的一個元素)。

在向參數傳遞引用類型的值時,會把這個值在內存中的地址複製給一個局部變量,所以這個局部變量的變化會反映在函數的外部!

重點時須要搞清楚引用類型的地址與指向地址的指針!!!

最後

公衆號:小何成長,佛系更文,都是本身曾經踩過的坑或者是學到的東西

有興趣的小夥伴歡迎關注我哦,我是:何小玍。 你們一塊兒進步鴨

相關文章
相關標籤/搜索