日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

web前端教程:分享引用類型與基本類型

 好程序員IT 2019-06-24

web前端教程:分享引用類型與基本類型,本文將從以下六個方面講解引用類型和基本類型

  1. 概念

  2. 內(nèi)存圖

  3. 引用類型和基本類型作為函數(shù)的參數(shù)體現(xiàn)的區(qū)別

  4. 引用類型的優(yōu)點(diǎn):

  5. 引用類型的賦值(對比基本類型)

  6. 淺拷貝和深拷貝

  以下為詳細(xì)內(nèi)容:

  1. 概念:

  基本類型也叫簡單類型,存儲的數(shù)據(jù)是單一的,如:學(xué)生的個數(shù)就是一個數(shù)字而已;引用類型也叫復(fù)雜類型,存儲的數(shù)據(jù)是復(fù)雜的,如:學(xué)生,包括學(xué)號,姓名,性別,年齡等等很多信息。從內(nèi)存(大家如果不懂內(nèi)存,請查閱相關(guān)資料)的角度來說:基本類型只占用一塊內(nèi)存區(qū)域;引用類型占用兩塊內(nèi)存區(qū)域。即定義基本類型的變量時,在內(nèi)存中只申請一塊空間,變量的值直接存放在該空間;定義引用類型的變量時(容易理解的是,我門看到new運(yùn)算符,一般就是定義引用類型的變量),在內(nèi)存中申請兩塊空間,第一塊空間存儲的是第二塊空間的地址,第二塊空間存儲的是真正的數(shù)據(jù);第一塊空間叫作第二塊空間的引用(地址),所以叫作引用類型。

  javaScript中的基本類型包括:數(shù)字(Number),字符串(String),布爾(Boolean),Null,Undefined五種;

  javascript的引用類型是:Object。而Array,Date是屬于Obejct類型。

  2. 內(nèi)存圖:

  如下代碼(都是定義了兩個局部變量):

  function demoFun(){

  var num = 20;//定義了一個基本類型的變量。

  var arr = new Array(12,23,34);//定義了一個引用類型的變量

  }

以上兩行代碼的內(nèi)存圖:

  可以看到,num變量只占用了一塊內(nèi)存區(qū)域;arr變量占用了兩塊內(nèi)存區(qū)域,arr變量在棧區(qū)(不懂棧區(qū)的人,先不要想太多)申請了一塊內(nèi)存區(qū)域,存儲著地址,存儲的地址是堆區(qū)的地址。而堆區(qū)中真正才存儲著數(shù)據(jù),所以說,arr變量占用了兩塊內(nèi)存區(qū)域。這樣看來,引用類型的變量好像還占用內(nèi)存多了。哈哈,不要著急,后面了解了引用類型的優(yōu)點(diǎn)后,你就會覺得這是問題了。

  當(dāng)我們讀取num變量的值時,直接就能讀到,但是當(dāng)我們要讀取arr里的值時,先找到arr中的地址,然后根據(jù)地址再找到對應(yīng)的數(shù)據(jù)。

  引用類型,類似于windows操作系統(tǒng)中的快捷方式??旖莘绞骄褪且粋€地址,真正的內(nèi)容是快捷方式所指向的路徑的內(nèi)容。如:我們把d:\t.txt文件創(chuàng)建一個快捷方式放在桌面上,那么,桌面上的快捷方式會占用桌面的空間,而d:\t.txt會占用d盤的空間,所以,占用了兩塊空間。

  基本類型就相當(dāng)于文件。

  引用類型,類似于我們在入學(xué)報名填寫報名表時,填寫家庭地址,這個家庭地址就相當(dāng)于第一塊空間,真正你家(第二塊內(nèi)存空間)不在報名表上。學(xué)校要找你家,先在報名表上找到你家的地址,然后根據(jù)地址,才能找到你家去。

  3. 引用類型的優(yōu)點(diǎn):

  引用類型作為函數(shù)的參數(shù)時,優(yōu)點(diǎn)特別明顯,第一,形參傳遞給實(shí)參時,只需要傳遞地址,而不需要搬動大量的數(shù)據(jù)(節(jié)約了內(nèi)存開銷);第二,形參對應(yīng)的數(shù)據(jù)改變時,實(shí)參對應(yīng)的數(shù)據(jù)也在改變(很多時候,我們希望這樣)。

  如以下代碼:

  先定義函數(shù)(冒泡排序)

  function bubble(arr){

  for(var i=0;i

  for(var j=0;j

  if(arr[j]>arr[j+1]){

  var temp = arr[j];

  arr[j] = arr[j+1];

  arr[j+1] = temp;

  }

  }

  }

  }

  當(dāng)調(diào)用冒泡排序時,

  var arr1 = [250,2,290,35,12,99];

  bubble(arr1);

  看看內(nèi)存以上代碼執(zhí)行時的,內(nèi)存變化:

  圖中,當(dāng)執(zhí)行,①對應(yīng)的代碼(var arr1 = [250,2,290,35,12,99];)時,內(nèi)存中會產(chǎn)生①對應(yīng)的變化,即在棧中申請一塊內(nèi)存區(qū)域,起名為arr1,在堆區(qū)中申請內(nèi)存空間放置250,2,290,35,12,99,并把堆區(qū)中的內(nèi)存的地址賦給arr1的內(nèi)存中;當(dāng)執(zhí)行②對應(yīng)的代碼bubble(arr1)時,調(diào)用函數(shù)。這時候會定義形參arr(內(nèi)存中③對應(yīng)的變化),即在棧中申請一塊內(nèi)存區(qū)域,起名為arr,并把a(bǔ)rr1保存的地址賦給了arr(內(nèi)存中②表示的賦值),這樣,形參arr和實(shí)參arr1就指向了同一塊內(nèi)存區(qū)域。數(shù)組中的值250,2,290,35,12,99在內(nèi)存中只有一份。即,不用把數(shù)組中每個元素的值再復(fù)制一份,節(jié)約了內(nèi)存。如果對內(nèi)存圖看懂了,那么,當(dāng)形參arr對應(yīng)的數(shù)據(jù)順序改變了,實(shí)參arr1對應(yīng)的數(shù)據(jù)順序也就改變了。即,實(shí)現(xiàn)了形參數(shù)據(jù)改變時,實(shí)參數(shù)據(jù)也改變了。所以,bubble函數(shù)不需要返回值,依然可以達(dá)到排序的目的??梢赃\(yùn)行我示例中的代碼,看看是不是達(dá)到了排序的效果。

  補(bǔ)充,基本類型作為函數(shù)參數(shù)的內(nèi)存變化:

  內(nèi)存圖:

  4. 引用類型變量的賦值:

  引用類型變量賦值時,賦的是地址。即兩個引用類型變量里存儲的是同一塊地址,也就是說,兩個引用類型變量都指向同一塊內(nèi)存區(qū)域。所以,兩個引用類型變量對應(yīng)的數(shù)據(jù)時一樣的。

  再如:

  var person1 = {

  name:"張三",

  sex:"男",

  age:12

  };

  var person2 = person1;

  person2.name="張四"; //這句話會改變person1和person2的name。說明person1和person2的name占用的是同一塊內(nèi)存。

  alert(person1.name+","+person1.sex+","+person1.age);

  alert(person2.name+","+person2.sex+","+person2.age);

  基本類型變量賦值時的內(nèi)存變化。

  5. 淺拷貝和深拷貝

  先說對象的復(fù)制,上面說了,引用類型(對象)的賦值,只是賦的地址,那么要真正復(fù)制一份新的對象(即克隆)時,又該怎么辦。

  var person1 = {

  name:"張三",

  sex:"男",

  age:12

  };

  var person2={};

  for(var key in person1){

  person2[key] = person1[key];

  }

  但是,當(dāng)一個對象的屬性又是一個引用類型時,會出現(xiàn)淺拷貝和深拷貝的問題。用一個自定義的object類型來說明問題。

  如:

  var person1 = {

  name:"張三",

  sex:"男",

  age:12,

  address:{

  country:"陜西",

  city:"渭南"

  }

  };

  //對象person1的address又是個對象,即,要對person1做真正的克隆,需要把a(bǔ)ddress中的每個屬性也進(jìn)行克隆。

  var person2={};

  for(var key in person1){

  person2[key] = person1[key];

  }

  person2.name="張四"; //不會改變掉person1的name屬性。

  person2.address.country="北京";//會改變掉person1的address.country

  大家注意看,person1和person2的name屬性各有各的空間,但是person1.address.country和person2.address.country是同一塊空間。所以,改變person2.address.country的值時,person1.address.country的值也會改變。這就說明拷貝(克隆)的不到位,這種拷貝叫作淺拷貝,而進(jìn)一步把person1.address.country和person1.address.name也拷貝(克隆)了,就是深拷貝。要做到深拷貝,就需要對每個屬性的類型進(jìn)行判斷,如果是引用類型,就再循環(huán)進(jìn)行拷貝(需要用到遞歸)。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多