標籤:ber define 一句話 table 變數 x11 記憶體 資料結構 lsp
在正式開始之前,我想先說兩句,理解javascript系列博文是通過帶領大家分析javascript執行時的記憶體配置情況,來解釋javascript原理,具體會涵蓋javascript預先載入,閉包原理,面象對象,執行模型,物件模型...,文章的視角很特別,也非常深入,希望大家能接受這種形式,並提供寶貴意見。
原始值和引用值
在ECMAScript中,變數可以存放兩種類型的值,即原始值和引用值。
原始值指的就是代表未經處理資料類型(基礎資料型別 (Elementary Data Type))的值,即Undefined,Null,Number,String,Boolean類型所表示的值。
引用值指的就是複合資料型別的值,即Object,Function,Array,以及自訂對象,等等
棧和堆
與原始值與引用值對應存在兩種結構的記憶體即棧和堆
棧是一種後進先出的資料結構,在javascript中可以通過Array來類比棧的行為
| 12345 |
var arr = []; //建立一個棧arr.push("apple");//壓入元素"apple" ["apple"]arr.push("orange");//壓入元素"orange" ["apple","orange"]arr.pop();//彈出"orange" ["apple"]arr.push("banana");//壓入元素"banana" ["apple","banana"] |
我們來看一下,與之對應的記憶體配置圖:
原始值是儲存在棧中的簡單資料區段,也就是說,他們的值直接儲存在變數訪問的位置。
堆是存放資料的基於散列演算法的資料結構,在javascript中,引用值是存放在堆中的。
引用值是儲存在堆中的對象,也就是說,儲存在變數處的值(即指向對象的變數,儲存在棧中)是一個指標,指向儲存在堆中的實際對象.
例:var obj = new Object(); obj儲存在棧中它指向於new Object()這個對象,而new Object()是存放在堆中的。
那為什麼引用值要放在堆中,而原始值要放在棧中,不都是在記憶體中嗎,為什麼不放在一起呢?那接下來,讓我們來探索問題的答案!
首先,我們來看一下代碼:
| 123456789101112 |
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為基礎資料型別 (Elementary Data Type),它們的值,直接存放在棧中,obj,person,arr為複合資料型別,他們的引用變數儲存在棧中,指向於儲存在堆中的實際對象。
由可知,我們無法直接操縱堆中的資料,也就是說我們無法直接操縱對象,但我們可以通過棧中對對象的引用來操作對象,就像我們通過遙控機操作電視機一樣,區別在於這個電視機本身並沒有控制按鈕。
現在讓我們來回答為什麼引用值要放在堆中,而原始值要放在棧中的問題:
記住一句話:能量是守衡的,無非是時間換空間,空間換時間的問題
堆比棧大,棧比堆的運算速度快,對象是一個複雜的結構,並且可以自由擴充,如:數組可以無限擴充,對象可以自由添加屬性。將他們放在堆中是為了不影響棧的效率。而是通過引用的方式尋找到堆中的實際對象再進行操作。相對於單一資料型別而言,單一資料型別就比較穩定,並且它只佔據很小的記憶體。不將單一資料型別放在堆是因為通過引用到堆中尋找實際對象是要花費時間的,而這個綜合成本遠大於直接從棧中取得實際值的成本。所以單一資料型別的值直接存放在棧中。
總結:
程式很簡單,但它是一切的根本,基礎是最重要的,因為摩天大廈也是一塊磚一塊瓦的搭建起來的。
記憶體是程式執行的根本,搞懂了記憶體,就等於搞懂了一切。
心血之作,鼓勵一下自已,加油!
參考:
JavaScript進階程式設計
理解Javascript_01_理解記憶體配置【轉】