JS中的棧和堆

學(xué)過數(shù)據(jù)結(jié)構(gòu)的同學(xué)對于棧和堆都多少有點了解吧!不了解也沒關(guān)系,學(xué)習(xí)JS中的棧和堆也一樣的_,下面我們來看看棧和堆到底是何方神圣......

一.棧和堆

棧(stack):棧會自動分配內(nèi)存空間,會自動釋放,存放基本類型,簡單的數(shù)據(jù)段,占據(jù)固定大小的空間。
基本類型:String,Number,Boolean,Null,Undefined

堆(heap):動態(tài)分配的內(nèi)存,大小不定也不會自動釋放,存放引用類型,指那些可能由多個值構(gòu)成的對象,保存在堆內(nèi)存中,包含引用類型的變量,實際上保存的不是變量本身,而是指向該對象的指針。
引用類型:Function,Array,Object

二.區(qū)別

:所有在方法中定義的變量都是放在棧內(nèi)存中,隨著方法的執(zhí)行結(jié)束,這個方法的內(nèi)存棧也自然銷毀。

優(yōu)點:存取速度比堆快,僅次于直接位于CPU中的寄存器,數(shù)據(jù)可以共享;
缺點:存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。

:堆內(nèi)存中的對象不會隨方法的結(jié)束而銷毀,即使方法結(jié)束后,這個對象還可能被另一個引用變量所引用(參數(shù)傳遞)。創(chuàng)建對象是為了反復(fù)利用,這個對象將被保存到運行時數(shù)據(jù)區(qū)。

三.棧和堆的溢出

:可以遞歸調(diào)用方法,這樣隨著棧深度的增加,JVM維持著一條長長的方法調(diào)用軌跡,知道內(nèi)存不夠分配,產(chǎn)生棧溢出。
:循環(huán)創(chuàng)建對象,通俗點就是不斷的new 一個對象。

下面來看看傳值和傳址的區(qū)別
其實這兩者區(qū)別就是基本類型和引用類型的區(qū)別,話不多說看栗子

var a = [1,0,9,8,7];
   var b = a;
   var c = a[0];
   console.log(b);     //[1,0,9,8,7]
   console.log(c);     //1
   //改變數(shù)值
   b[1] = 3;
   c = 5;
   console.log(b[1]);  //3
   console.log(a[0]);  //1      

因為a是數(shù)組,是引用類型,賦給b的時候傳的是棧中的地址,不是堆內(nèi)存中的對象,c僅僅是從a堆內(nèi)存中獲取的一個數(shù)據(jù)值,并保存在棧中,所以b修改的時候,會根據(jù)地址回到a堆中修改,c則直接在棧中修改,并且不能指向a堆內(nèi)存中。

四.深淺拷貝

深淺拷貝在前端面試中經(jīng)常被問到,和大家分享一下,先來說說淺拷貝
淺拷貝:也就是只復(fù)制了第一層屬性,復(fù)制對象是基本類型
在復(fù)制基本類型時,直接使用等號完成,在復(fù)制引用類型時,循環(huán)遍歷對象,對每個屬性或值使用等號完成。

下面看個栗子

var color1 = ['red','green']; 
        var color2 = [];
        //復(fù)制
        for(var i  = 0;i < color1.length;i++){
          color2[i] = color1[i]; 
        }
        console.log(color2);  //[red,green]
        color1.push('black');
        console.log(color2);  //[red,green]

在這個栗子中,color2復(fù)制color1,因為數(shù)組中的每一項都是基本類型(string),假如數(shù)組中的某一項保存的是一個對象,或者是一個數(shù)組,又或者說對象的某一個屬性還是一個對象(也就是引用類型的某個屬性還是引用類型),此時淺拷貝就沒用了,那該怎么辦?
我們先來看一個引用類型屬性還是引用類型的栗子(有點繞口.....)

var person = {
    name : 'wang',
    score:{
            math:100,
        English:100
        }
    }

在上面這個小栗子中,score屬性還是一個對象。

下面繼續(xù)來說我們的拷貝,現(xiàn)在該深拷貝出場了......
深拷貝:對屬性中所有引用類型的值,遍歷到是基本類型的值為止,利用遞歸來實現(xiàn)深拷貝。
來看一個栗子

function cloneObject (obj) {
     var newObj = {}  //如果不是引用類型,直接返回
      if (typeof (obj) !== 'object') {
          return obj
     }
     //如果是引用類型,遍歷屬性
    else{
        for (var attr in obj) {
        //如果某個屬性還是引用類型,遞歸調(diào)用
        newObj[attr] = cloneObject(obj[attr])
                }
       }
    return newObj
  }

對于深拷貝,我們先判斷它是否為引用類型,如果不是,直接返回
如果是,循環(huán)遍歷該對象的屬性,如果某個屬性還是引用類型,則針對該屬性再次調(diào)用deepClone函數(shù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 內(nèi)存管理 簡述OC中內(nèi)存管理機制。與retain配對使用的方法是dealloc還是release,為什么?需要與a...
    丶逐漸閱讀 2,081評論 1 16
  • __block和__weak修飾符的區(qū)別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,592評論 0 6
  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,790評論 11 349
  • 1.筆的空性 吳妍一來,我就變成了憤怒的小鳥,到處發(fā)火,我感覺她在指責(zé)我,然后很不耐煩,然后是總是不按照計劃來,本...
    柔光寶寶閱讀 260評論 0 0
  • 原本打算在家宅一天,在小姐妹兒召喚,勤快的洗了個頭,因為一個女生如果愿意洗頭再出門見人,這是對這個人極大的尊重,像...
    多如艾米閱讀 306評論 4 2

友情鏈接更多精彩內(nèi)容