堆棧和垃圾回收

堆棧

堆(heap)和棧(stack)
堆: 為程序員動態(tài)分配的內(nèi)存,大小不定也不會自動釋放,特點是先進先出;
棧: 為自動分配的空間,它由系統(tǒng)自動釋放,特點是后進后出。

基本數(shù)據(jù)類型存放于棧內(nèi)存中,Undefined Null String Number Boolean,它們是直接按值存放的,可以直接訪問。

引用數(shù)據(jù)類型存放于堆內(nèi)存中,變量只是保存的一個指針,該指針指向堆內(nèi)存中的地址,當訪問引用類型數(shù)據(jù)(Array、Object、Function等)時,先從棧中獲得該對象的指針,再從堆中取出對象的數(shù)據(jù)。

值傳遞和地址傳遞

var a = 10;
var b = a;
b = 20;
console.log(a,b);
//以上的代碼修改 b 的值并不會影響 a 的值

var a = [1,2,3,4];
var b = a;
var c = a[0];
console.log(b);
console.log(c);
b[0] = 9;
c = 10;
console.log(a);//[9,2,3,4]
//以上代碼可以看出 當改變 b 中的數(shù)據(jù)時,a 中的數(shù)據(jù)也發(fā)生了變化;改變 c 的 數(shù)據(jù)時,a 不會受影響
//a 是數(shù)組,屬引用類型,當將 a 賦值給 a 時,傳遞的是棧中的地址,而不是堆內(nèi)存中的對象。
//而 c 只是從 a 堆內(nèi)存中獲取的一個數(shù)據(jù)值,保存于棧中。修改 c 時,是在棧中直接修改

深拷貝與淺拷貝

在定義引用數(shù)據(jù)類型時,變量存放的只是一個地址。當使用對象拷貝,傳遞的也只是一個地址。因此在訪問拷貝對象屬性時,會根據(jù)地址找到源對象指向的堆內(nèi)存中。

淺拷貝

淺拷貝.PNG
var obj1 = {
    name : "zhar",
    desc : ["北京"]
}
function copy(o1){
    var newObj = {};
    for(var key in o1){
        newObj[key] = o1[key];
    }
    return newObj;
}
// var obj2 = obj1;
var obj2 = copy(obj1);
obj2.name = "tom";
obj2.desc.push("昌平");
console.log(obj1);//{ name: 'zhar', desc: [ '北京', '昌平' ] }

深拷貝

深拷貝.PNG
var obj1 = {
    name : "zhar",
    desc : ["北京"]
}
function copy(obj,target){
    var newObj = target || {};
    console.log(obj)
    for(var key in obj){
    //判斷是不是引用數(shù)據(jù)類型,即是不是對象
        if(typeof obj[key] === "object"){
            newObj[key] = (obj[key].constructor===Array)?[]:{};
//第二次調(diào)用時,要傳入target即newObj[key],newObj[key]要重復使用
            copy(obj[key],newObj[key]);
        }else{
            newObj[key] = obj[key];
        }
    }
    return newObj;
}
var obj2 = copy(obj1);

深拷貝就是為了解決淺拷貝時數(shù)據(jù)互相影響而存在的

垃圾回收

Javascript 具有自動垃圾回收機制,執(zhí)行環(huán)境會管理代碼執(zhí)行過程中使用的內(nèi)存。

使我們不必像 C 或 C++開發(fā)者那樣,手動去管理內(nèi)存的釋放。

自動回收機制原理:

垃圾回收器按照固定的時間間隔找出不再繼續(xù)使用的變量,然后釋放其占用的內(nèi)存。

兩種策略:

  1. 標記清除(現(xiàn)在瀏覽器都在使用)
    最常用的垃圾回收方式。當變量進入環(huán)境時,將變量標記為"進入環(huán)境";當變量離開環(huán)境時,將其標記為"離開環(huán)境"。
    到2008年,各瀏覽器使用的清除策略都是標記清除,差別在于時間間隔不同
  2. 引用計數(shù)(已被棄用)
    引用計數(shù)是跟蹤每個值被引用的次數(shù);當有一個變量被引用時,則這個值的引用次數(shù)加1,當取消一個引用時,次數(shù)減1。當引用值變?yōu)? 時,將由垃圾收集器回收
    引用計數(shù)方式有嚴重的問題,就是,當變量相互引用時,如:
var obj1 = {}
var obj2 = {}
obj1.a = obj2;
obj2.b = obj1;

對于上面的代碼,存在相互引用,其引用計數(shù)永遠為2,就會導致對象永遠不會被回收。

前端程序員最簡單粗暴的釋放內(nèi)存的方式:

obj = null;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容