您好,登錄后才能下訂單哦!
這篇文章主要講解了javascript內存模型的用法,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。
當我們聲明變量、初始化變量、更改變量值的時候,到底會發生什么?JavaScript 是如何實現這些基本的功能?最重要的是,我們如何才能理解這些基礎知識?
本文將覆蓋以下 4 個方面:
從一個簡單的栗子開始。首先我們聲明一個叫myNumber
的變量,賦值為 23。
let myNumber = 23
執行這段代碼的時候,JavaScript 會...
通常我們會說:“myNumber 等于 23”,但從技術上講,myNumber
等于一個內存地址,那兒保存著一個大小為 23 的值。理解這段話十分關鍵。
如果我們創建一個 newVar
的新變量,然后把 myNumber
賦值給它:
let newVar = myNumber
因為 myNumber
實際上等于“0012CCGWH80”,那么newVar
也等于“0012CCGWH80”,這個內存地址保存的值為 23。最終實現了“newVal 等于 23”的效果。
如果我們這樣做又會發生什么呢?
myNumber = myNumber + 1
顯然,myNumber
的值為 24,那么對于指向相同內存地址的newVar
,它是否也等于 24?
答案當然是否定的!因為 JavaScript 的基本數據類型是不可變的,myNumber + 1
的結果是 24,JavaScript 會分配一個新的內存地址來存儲這個值,然后將myNumber
指向這個新地址。
圖3
再舉一個例子:
let myString = 'abc' myString = myString + 'd'
JS 新手可能認為,字符串abc
已經存在于內存里,所以字母d
只是追加到它的后面。從技術上講,這是錯誤的。由于原始數據類型的不變性,當abc
與d
結合時,JS 會分配一個新的內存地址來保存這個值(abcd
),接著myString
指向新的地址。
圖4
JS 的內存模型可以簡單的理解為兩個不同的區域:調用棧和堆。
圖5
棧用來保存原始數據以及函數調用,可以粗略的用下圖表示。
圖6
上圖中,我抽象的在調用棧中顯示每個變量的值。但請記住,變量實際指向的是內存地址,那里保存著對應的值。這是理解let vs. cont
的關鍵。
關于堆內存。
堆保存著所有非原始類型的數據。它和棧最大的區別是,堆可以保存無序、能夠動態增刪的數據——對于對象和數組來說,這是完美的存儲空間。
還是從一個簡單的栗子開始。下面,我們聲明一個叫myArray
的變量,并初始化一個空數組。
let myArray = []
當 JS 引擎執行上面的代碼,內存會發生如下變化:
圖8
現在,我們可以對數組做任何操作了。
myArray.push('first') myArray.push('second') myArray.push('third') myArray.pop()
圖9
我們應該優先使用const
而不是let
,除非變量會被改變。
我們必須清楚的知道——“改變”到底是什么意思。
值發生了變化,這是對“改變”的一種錯誤理解。一些 JS 程序員會寫下這樣的代碼:
let sum = 0 sum = 1 + 2 let numbers = [] numbers.push(1) numbers.push(2)
這段代碼正確的使用let
聲明變量sum
,因為值被改變了。然而卻錯誤的使用let
來聲明變量numbers
,因為他們認為給數組 push 一些數據后,數組的值被改變了。
“改變”的正確解釋是——內存地址變了。let
允許你改變內存地址,const
則不允許。
const importantId = 489 importantId = 100 // TypeError: Assignment to constant variable
一起看看這到底發生了什么。
當聲明importantId
時,JS 引擎為其分配一個內存地址,并存儲一個大小為 489 的值。切記,變量importantId
等于這個內存地址。
圖10
當把 100 賦值給importantId
時,因為 100 是原始類型,此時會分配一個用來存儲 100 的內存地址。然后 JS 嘗試將新的內存地址賦值給importantId
,此時就會發生錯誤。這是我們想要的結果,因為我們不想改變一個非常重要的 ID。
圖11
對于新手來說,由于不清楚“改變”的真是含義,在使用 const 聲明變量可能會有些困惑,所以他們默認使用 let 來避免麻煩。
然而,這并不是推薦的做法。Google 在他們的 JavaScript 風格指南中寫道:“使用 const 或 let 聲明所有變量。除非變量會被重新賦值,否則優先使用 const。一定不要使用 var”。
他們沒有明確說明為什么要這樣做,但我認為這樣做有以下好處:
看完上述內容,是不是對javascript內存模型的用法有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。