標籤:

「每日一題」JS里基本類型(值)和複雜類型(引用)有什麼區別?

短答案:

1. 基本類型變數存的是值,複雜類型的變數存的是內存地址。

2. 基本類型在賦值的時候拷貝值,複雜類型在賦值的時候只拷貝地址,不拷貝值。

長答案:

在講解這個問題之前,我們需要看一下計算機是如何儲存變數的。

如果計算機要存儲一個整數,它可以用 32 個位(bit)來存儲,一個小數,可以用 64 位來存儲。但不管怎樣,位數都是固定的。

假設有如下 JS 代碼:

var a = 1.23nvar b = 3.14n

對應的內存是這樣:

接下來加幾行代碼:

var obj = {}nvar c = 1.628n

現在,計算機遇到一個難題,到底用多少位來存 obj 呢?

用固定位數有一個問題,如果程序員之後往 obj 上添加屬性(如 obj.a = 1.23; obj.b = 2.34),那麼 obj 用的位數可能放不下這兩個小數。

有人說,「那給 obj 分配足夠多的位數不就好了,比如一萬位,總夠用吧?」不行,這樣做一來浪費內存,二來一萬位也不一定夠用,萬一 obj 裡面的屬性非常多呢?

引入另一種內存

為了解決 obj 存儲的問題,計算機將程序里的內存分成兩種,一種是上圖所示,按順序使用用內,每個數據佔據的位數是固定的,這種內存叫做「棧內存」;另一個,就是專門用來存儲位數不固定的數據,存的時候不一樣按順序一個一個存,這種內存叫做「堆內存」。

我們來看 obj 應該怎麼存儲:

如圖, obj 在棧內存那裡,只佔固定位數(32位或64位或其他都可以),裡面存的並不是數據{a:1.23,b:2.34},裡面存的是數據「在內存中的位置」(類似於引用或者指針)。

堆內存里,會開闢一塊空間來存放 {a:1.23, b:2.34}。

「如果我再給 obj 添加一個屬性怎麼辦呢?obj.c = 3.45」

好問題,那麼 obj.c 依舊會放到堆內存,同時佔用的內存空間也會動態的變化,以盛放 obj.a、obj.b 和 obj.c 三個小數。具體怎麼動態變化,則是由 JS 引擎來負責的,暫且不表(我也不會)。

值 V.S. 引用

如果變數存儲的是原始值,那麼這個變數就是值類型,在 JS 里也叫做基本類型。

如果變數存儲的是內存位置,那麼這個變數就是引用類型,在 JS 里也叫複雜類型,也就是對象。

值類型在賦值的時候是直接拷貝的,而引用類型則只拷貝地址。

值類型的賦值舉例:

var a = 1.23nvar b = an

對應的內存結果為:

引用類型的賦值舉例:

var a = {name: a}nvar b = an

對應內存結果為:

也就是說,a 和 b 都存儲著「同一塊內存」的地址!那麼就會有一個問題:

當我們修改 b.name 的時候,a.name 也會跟著變:

b.name = bna.name === b // truen

以後再說如何解決這個問題。

以上,就是對「值」和「引用」的區別的淺析。想了解更多前端知識,請加 Q 群:222459918。


推薦閱讀:

一道面試題所引發的運算符的優先順序的思考
「每日一題」JSONP 是什麼?
慢時光
引入 CSS 的方式
前端開發者應知必會:瀏覽器是如何渲染網頁的

TAG:前端入门 |