本文會同步到我的個人網站中。
在ECMAScript中,變量可以存放兩種類型的值
- 原始值
- 引用類型值
原始值指的是代表原始數據類型的值,例如:undefined null number string boolean
引用類型指的是複合類型值,例如:object function array 自定義對象
堆和棧
- 棧是一種LIFO的數據結構,即後進先出,隊列是一種FIFO的數據結構,即先進先出
- 堆是基於散列算法存放數據的一種數據結構
- 原始值是存放在棧中的簡單數據段,它們的值直接存儲在變量訪問的位置,例如:
var num = 10; //變量名num和初始化值10都存放在棧中 複製代碼
- 引用值是存放在堆中的對象,引用值的變量名是一個存放在棧中指針,指向堆中的引用值對象,例如:
var obj = new object(); //變量名obj存放在棧中,而它指向的object()對象是存放在堆中的 複製代碼
爲什麼原始值要放在棧中,引用值要放在堆中?
- 先看一段代碼
function Person(id,name,age){ this.id = id; this.name = name; this.age = age; } var num = 10; var bol = true; var str = "abc"; var obj = new Object(); var arr = ['a','b','c']; var person = new Person(100,"笨蛋的座右銘",25); 複製代碼
- 內存分析
- 原始類型變量num bol str的變量名和內容都存放在棧中
- 引用類型變量obj arr person的變量名作爲指針存放在棧中,指向堆中的變量內容
由上圖可以看出,我們不能直接操作堆中的數據,也就是說不能直接操作對象,但我們可以通過棧中存放的變量指針來進行操作
- 爲什麼要分堆和棧
堆比棧大,棧比堆的運算速度快,對象是一個複雜的結構,並且可以自由擴展,如:數組可以無限擴充,對象可以自由添加屬性。將他們放在堆中是爲了不影響棧的效率。而是通過引用的方式查找到堆中的實際對象再進行操作。相對於簡單數據類型而言,簡單數據類型就比較穩定,並且它只佔據很小的內存。不將簡單數據類型放在堆是因爲通過引用到堆中查找實際對象是要花費時間的,而這個綜合成本遠大於直接從棧中取得實際值的成本。所以簡單數據類型的值直接存放在棧中
總結
- 兩種變量類型:原始值和引用類型值
- 變量在內存中的存放位置分爲堆和棧