咱們學習Javascript,首先學習的就是變量的數據類型,ES6版Javascript內置了7種數據類型:html
符號(Symbol)程序員
最新規範中,還增長了
整數(BigInt)
類型,這裏暫且不論。
這裏有幾個問題:編程
let a = 1 let b = a b = 2
let a = 1 let b = a function foo(c, d) { c = c + d } foo(a, b)
let a = { value: 1 } let b = a b.value = 2
let a = { value: 1 } let b = a function foo(c, d) { c = c + d } foo(a.value, b.value)
答案能夠本身跑一下,爲何能夠在後文中尋找。緩存
爲了更好的理解,咱們從最底層的彙編語言提及。數據結構
爲何須要彙編語言,你們都知道機器語言是二進制的,爲了容易讀寫,彙編語言在二進制的基礎上加上了指令名稱,好比加法指令00000011
,彙編裏面就是add
,這樣人類纔好閱讀和編寫機器能讀懂的指令程序。執行時轉換成對應的二進制碼便可。編程語言
再到後來,高級語言發展愈來愈快,它們的語法更接近人類的思惟方式,更受程序員歡迎。它們怎麼執行呢?運行以前,它們的編譯器會把高級語言代碼編譯成機器能讀懂的二進制編碼。函數
二進制編碼怎麼運行呢,咱們須要再瞭解兩個概念:寄存器和內存。佈局
寄存器
,cpu只能運算,寄存器是輔助執行運算的存儲器,存儲內容諸如:參與運算的數據的內存地址、當前所需運行的指令的地址內存
,內存分爲兩種:cpu緩存和內存。學習
簡單描述一下運算的過程:根據寄存器的地址,到內存讀取到運算指令,運算數據,而後在運算單元執行運算。編碼
從上面能夠了解到,程序運行數據是存放在內存中,下面咱們來看看數據在內存中是怎麼佈局的。
內存是按地址訪問的,好比,咱們有512Kb的內存,那麼內存地址就是從0x0000
到0x8000
。
內存佈局會涉及兩個概念:棧和堆
。
棧
,從內存高位往地位分配,從0x8000
開始,假如咱們要分配一個4字節的變量,那麼變量就是從0x8000
到0x7eec
。棧是用來存儲函數運行時數據,如局部變量。學過數據結構就知道,棧是後進先出的,這個就是要知足函數調用的順序,函數是一層層往下調用,而後一層層往上釋放。堆
,從內存低位往高位分配,從0x1000
開始(0x1000
如下由系統使用),堆用來存儲動態變量,須要使用者本身申請和釋放(大多高級語言有垃圾回收機制,因此無需管理)。以上這些就是彙編語言的基本存儲和運行邏輯,更多參看參考文檔1。
鋪墊了這麼多,最後咱們回來看看Javascript的變量,究竟是怎麼存儲和修改的。
從存儲和訪問角度,Javascript的原生數據類型還要分爲原始類型和高級類型。
說簡單一點,原始類型就是能夠按值訪問的數據類型;高級類型就是按引用訪問的數據類型。存儲方式也不同,基本類型的變量是存放在棧區的(棧區指內存裏的棧內存);引用類型的值是同時保存在棧內存和堆內存中的對象。
這裏的棧和堆和彙編語言還有區別,假如咱們用的是v8引擎,Javascript的內存分配底層是由v8管理的。具體參看參考文檔2。
編程語言中的變量名,編譯運行時關聯的就是變量的地址。
變量的修改也是分原始類型和高級類型。
原始類型,賦值就是修改變量地址存放的數據,也就是直接被修改了。
那麼問題來了,函數的原始類型參數會被修改嗎?字符串呢?
高級類型,直接賦值修改的實際上是引用自己,並不是對象的值(引用其實你也能夠理解爲是一個數據變量)。你想修改對象的屬性,必須經過引用訪問到對象結構,而後再訪問到屬性值,再作修改。
函數對象類型參數,能夠被修改嗎?
以上就是所有內容,最後的題目請仔細思考一下,歡迎與我討論。
我的讀書公衆號,歡迎交流!