按值傳遞和引用傳遞

歡迎你們關注個人 githubgit

概述

最近在看到函數按值傳遞仍是引用傳遞的時候產生了困惑,忽然想到這個問題好像從第一次看紅寶書就一直有這個困惑,因而各類搜,可是網上的種種回答也很不相同,想了兩天終於算是有個理由能夠說服本身了。咱們先不討論按值傳遞和引用傳遞的名字的定義,不少時候都是被名字的定義誤導了。github

實質重於形式,名字能夠有不少,咱們就不討論到底該叫什麼。只想說在現代的語言中參數的傳遞方式只有按值傳遞了,好比JS,沒有引用傳遞。我當時比較困惑是將引用類型的複製當成了引用傳遞,準確的講這應該叫引用訪問,好像這是文字遊戲的感受。下面來簡單的說一下。函數

基本概念

JS的值分爲基本類型和引用類型spa

  • 基本類型:存儲在棧中,由於佔據的空間固定,存儲在棧中更容易查找變量的值設計

  • 引用類型:存儲在堆中,由於引用值大小會改變,因此不能放在棧中,否則會下降查詢效率。可是能夠將該引用值的地址存儲在棧中,地址的大小是固定的。code

當咱們訪問一個對象的時候,首先獲得的是從棧中找到的該對象在堆內存中的地址,而後按照地址去獲取對象中的值。cdn

當咱們複製基本類型變量和引用類型變量的時候對象

  • 基本類型複製:在棧中新開一個字段,將值複製到新字段,新值和舊值是兩個獨立的字段,互不影響blog

  • 引用類型複製:在棧中新開一個字段,將對象在堆內存中的地址(引用)複製到新字段,新值和舊值指向堆內存中的同一個對象,當咱們要操做變量的時候,操做的是變量的引用。當給對象添加屬性的時候,操做的是堆內存中實際的對象遊戲

基本類型的複製:

引用類型的複製:

傳遞參數

當咱們傳遞引用類型的參數時,就是引用類型的複製,函數的形參仍是和實參指向了同一個引用類型,此時操做變量是操做的變量的引用,當給對象添加屬性的時候,操做的是堆內存中實際的對象。咱們能夠認爲是按地址傳遞

當咱們操做變量的時候,實際是:

因此咱們就能夠理解下面的這些代碼了:

function setName(obj) {
    obj.name = 'zhangsan'   // 操做的是堆內存中的對象
}

var person = new Object()
setName(person)
console.log(person.name)  // zhangsan
複製代碼

function setName(obj) {
    obj.name = 'zhangsan'
    obj = new Object()      // 操做的是對象的引用
    obj.name = 'lisi'
}

var person = new Object()
setName(person)
console.log(person.name) // zhangsan
複製代碼

因此說函數是按值傳遞參數,JS沒有引用傳遞



參考資料:

《JS高級程序設計》

https://www.zhihu.com/question/27114726

https://www.zhihu.com/question/51018162

相關文章
相關標籤/搜索