一、基本類型和引用類型的值 1.基本類型和引用類型的值 基本類型值:指那些保存在棧記憶體中的簡單數據,即這種值完全保存在記憶體中的一個位置,他們所占據的空間大小是固定的。 引用類型值:指那些保存在堆記憶體中的對象,這些類型的真正數據是保存在堆記憶體中的,而同時在棧記憶體中保存的只是一個指針,這個指針指向的是這 ...
一、基本類型和引用類型的值
1.基本類型和引用類型的值
基本類型值:指那些保存在棧記憶體中的簡單數據,即這種值完全保存在記憶體中的一個位置,他們所占據的空間大小是固定的。
引用類型值:指那些保存在堆記憶體中的對象,這些類型的真正數據是保存在堆記憶體中的,而同時在棧記憶體中保存的只是一個指針,這個指針指向的是這個對象在堆記憶體中的一塊地址。
基本類型的複製:基本類型在記憶體中占有的空間大小是固定的,複製的時候會重新在棧記憶體中開闢一塊空間,是按值來訪問的。
引用類型的複製:由於這種對象所占的大小是不固定的,是放在堆記憶體中的,但是記憶體的地址大小是固定的,故棧中存放的是對象在堆記憶體的地址。這樣當查找引用的時候,是先從棧記憶體中取出地址,然後再到堆記憶體中找到對應的值,這就是引用訪問。複製的時候是複製的棧記憶體的值,也就是拷貝的一個引用而已,兩個變數指向的堆記憶體中對象還是同一個對象。
2.複製變數的值
基本類型:複製的是變數本身的值,複製後是在棧空間重新開闢一塊空間,複製完成後兩個變數是相互獨立的,各不相干,故一個變數的值改變後不會影響另外一個變數的值。
引用類型:複製的時候只是複製的棧空間的地址,而堆記憶體中還是同一個對象,也就是複製的引用,結果是兩個變數指向的是同一個記憶體塊,所以,複製後兩個變數中某一個改變了對象的值那麼另外一個變數輸出的結果也會改變,因為他們是指向的記憶體中同一個對象。
3.傳遞參數
在js中參數傳遞都是值傳遞,不存在引用傳遞。
值類型:傳遞的是變數本身的值,和複製是一樣的,函數中改變了變數的值,不會影響源變數值
引用類型:同樣是值傳遞,傳遞的是變數再棧記憶體空間中的地址值,如果在函數中改變了對象某一個屬性的值,源變數中的值也會改變,因為在堆記憶體中它們是指向的同一個對象。
function func(num){ num.name=123; } var box={}; box.name='abcd'; alert(box.name); //abcd func(box); alert(box.name); //123 值在函數func中被改變了
4.檢測類型
檢測變數的類型的時可以用 typeof 來實現,但是這個只是返回的幾大基本的數據類型,在檢測Object類型的時候則不是那麼好用,因為Null,Object,Array,RegExp 等都會返回object,那樣就不知道變數到底是什麼類型。
可以 用instanceof 來確定變數是某種具體的引用類型。
var box = [1,2,3]
alert(box instanceof Object); //true alert(box instanceof Array); console.log(Array.isArray(box)) //true //準確檢測類型是否是數組 如果是這種類型就返回true,否則就返回false
二、執行環境及作用域
執行環境也就是作用域在很多的編程語言中都是一個很重要的概念,規定了變數或者函數有權訪問其他數據的許可權,規定了各自的行為。
全局執行環境是最外圍的執行環境,在web瀏覽器中,全局執行環境被認為是window對象,故所有的全局變數和函數都是以window對象的屬性和方法創建的。
每個函數都有自己的執行環境,當執行環境中代碼執行完成後,就會銷毀該執行環境,也會銷毀裡面的變數和函數等。(全局執行環境是需要在網頁關閉或者應用程式退出後才會被銷毀。)
當代碼在一個環境中執行時,會創建變數對象的一個作用域鏈,作用域鏈的用途是保證執行環境有權訪問的所有變數和函數的有序訪問。
函數體內還包含著函數,只有這個函數才可以訪問內一層的函數。而內部函數的變數可以通過作用域鏈訪問外部函數的變數,可以向上搜索作用域鏈,以查詢變數。但是不能反過來。
沒有塊級作用域
塊級作用域表示諸如if等有花括弧封閉的代碼段塊,所以支持條件判斷來定義變數。 像 if,for 等代碼塊中定義的變數在花括弧外面是可以訪問的,這和其他語言中有很大的差別。
if(true){ var color = 'red'; } console.log(color); //red
var關鍵字在函數中的區別
在函數中聲明變數的時候,如果不加上關鍵字 var 那變數會被認為是全局的,函數外面也可以訪問它,當然在訪問之前要先執行一次函數,加了則是局部的。
最好不要不用var關鍵字就初始化變數,因為這種情況下可能會導致各種錯誤,所有初始化變數的時候一定要加上關鍵字 var。
一般確定某一個變數的時候是通過搜索來確定的,現在本級作用域上找,如果沒有,在向上級作用域找,依次類推,故訪問局部變數要比訪問全局變數的效率更高。因為不需要向上收索作用域鏈
3、記憶體相關
js中也存在垃圾回收機制,我們不需要擔心記憶體的泄露問題,垃圾回收機制會自動的管理記憶體的分配和無用記憶體的回收。
JS中最常用的垃圾回收的方式是標記清除,就是在運行的時候會給記憶體中的所有變數加上一個標記,然後去掉環境中正在使用的變數的標記,而沒有被去掉標記的變數將被視為準備刪除的變數。最後垃圾清理器完成記憶體清理的工作,銷毀那些帶有標記的變數,並且回收他們所占用的記憶體空間 。
垃圾收集器是周期性的運行,不是隨時運行,這樣可能會遇到一些性能問題,但是一般情況下不需要擔心這個問題。
一般來說,確保頁面占用的記憶體更少可以讓頁面獲得更好的性能,最好的減少記憶體占用量的方式就是,一旦變數或者對象不再使用的時候,將其賦值為空,即:box=null; 來釋放引用,這種方式叫做刪除引用,這種方式使用大多數的全局變數和全局對象。