#hello痊末,JS:05引用類型和深淺拷貝

一、基本類型VS引用類型

注: 這里的內(nèi)存涩笤,為虛擬內(nèi)存

1蹬碧、引用類型:

  • 定義:保存在堆內(nèi)存中的對(duì)象炒刁,變量中保存的實(shí)際上只是一個(gè)指針,這個(gè)指針執(zhí)行內(nèi)存中的另一個(gè)位置罗心,由該位置保存對(duì)象
  • 包括:對(duì)象渤闷、數(shù)組脖镀、函數(shù)、正則

假設(shè)變量中有一個(gè)函數(shù)补憾,函數(shù)內(nèi)東西特別多(或者有一個(gè)對(duì)象,對(duì)象里的數(shù)據(jù)特別大)腾务,這里可選堆的空白處存放函數(shù)、對(duì)象的數(shù)據(jù)(隨機(jī)選擇未使用的空白堆窿撬,隨意變大變行鸱病),放在堆中的均為引用類型

2跛璧、基本類型(值類型):

  • 定義:指的是保存在棧內(nèi)存中的簡(jiǎn)單字段(成塊排列追城,棧燥撞,允許放進(jìn)去拿出來)
  • 包括:數(shù)值(number)物舒、布爾值(boolean)、null锋玲、undefined涵叮、string(在賦值傳遞中會(huì)以引用類型的方式來處理)

棧里面仍存有變量割粮,只不過存放的不是數(shù)據(jù),而是大數(shù)據(jù)地址廷雅,比如這個(gè)地址為0x0011,棧內(nèi)存放的東西京髓,均為可控堰怨、較小容量。從一個(gè)變量向另一個(gè)變量賦值基本類型時(shí)灿巧,會(huì)在該變量上創(chuàng)建一個(gè)新值抠藕,然后再把該值復(fù)制到為新變量分配的位置上。

3敬辣、實(shí)例一:基本類型

  var a 
  var b 
  var obj 
  var obj2
 
 a =  1;
 b =  2; 
 var obj =  { 
     name:  'xiaoqin', 
     sex:  'male', 
      age:  30,
      friend:  { 
name:  'hello', age:  100 
      } 
 }  
var newObj =  {}
     b = a; 
     console.log(b)
  //返回1

如圖:


image

(1)基本類型的值被賦值給另一個(gè)變量购岗,其實(shí)就是分配內(nèi)存空間
一開始门粪,a的值為 1 玄妈,當(dāng)使用a 來初始化b 時(shí),b 值此時(shí)為1绎签。但b中的1與a中的是完全獨(dú)立的诡必,該值只是a中的值的一個(gè)副本搔扁。說明在棧里變量再次變化稿蹲,但這個(gè)兩個(gè)變量可以參加任何操作而相互不受影響。

總結(jié):
一個(gè)變量賦值給另一個(gè)變量時(shí)涂炎,其實(shí)是分配了一塊新的內(nèi)存空間设哗。按照以上操作网梢,基本類型在賦值操作后,事實(shí)上就a分配了一塊新內(nèi)存空間給b蛀序,兩個(gè)變量是相互不受影響活烙。

(2)基本類型的比較是值的比較 只有在它們的值相等的時(shí)候它們才相等啸盏。 當(dāng)比較的兩個(gè)值的類型不同的時(shí)候==運(yùn)算符會(huì)進(jìn)行類型轉(zhuǎn)換,但是當(dāng)兩個(gè)值的類型相同的時(shí)候气笙,即使是==也相當(dāng)于是===潜圃。

var a = 1;
var b = true;
console.log(a == b);//true

(3)基本類型的變量其實(shí)就是存放在棧區(qū)舟茶。結(jié)合以上吧凉,棧區(qū)指內(nèi)存里的棧內(nèi)存,但是棧區(qū)里包括了變量名和變量值胀瞪。

4饲鄙、實(shí)例二:(續(xù)上面的例子)引用類型

(1)引用類型的值是可變的
可為引用類型添加屬性和方法忍级,也可以刪除其屬性和方法颤练。
看一下這個(gè)例子:一個(gè)為引用類型的變量賦值給另一個(gè)為引用類型的變量

  var obj2 = obj //控制臺(tái)測(cè)試一下二者的值
 obj
//  {name:  "ruoyu", sex:  "male", age:  30, friend:  {…}} 
obj2
 // {name:  "ruoyu", sex:  "male", age:  30, friend:  {…}}

值是一樣的。因為var obj2=obj患雇,即通過obj的值(一個(gè)對(duì)象)賦值給obj2宇挫,那么obj2的值就是賦值后原本obj對(duì)應(yīng)屬性和值器瘪。作為一個(gè)引用類型,它被放在堆中援所。所以尋找obj2則在堆里找到住拭,只是換了另一個(gè)名字為obj2

如圖:


image

總結(jié):
原本在棧中的對(duì)象分別指向了同一個(gè)堆滔岳,那么存放在堆中即為對(duì)象的內(nèi)存地址。引用類型的賦值其實(shí)是對(duì)象保存在棧區(qū)地址指針的賦值摊求,因此兩個(gè)變量指向同一個(gè)對(duì)象室叉,任何的操作都會(huì)相互影響寥闪。

(2)引用類型的比較是引用的比較
A疲憋、我們先看一下基本類型值的比較:

var obj3 =  '{name: 'hello'}';  
var obj4 =  '{name: 'hello'}';
 console.log( obj3 == obj4 ); 
 // true

總結(jié):
可以得出基本類型的比較:當(dāng)兩個(gè)比較值的類型相同(如字符串)的時(shí)候缚柳,相當(dāng)于是用 === ,所以輸出是true彩掐。

B堵幽、再來看一下引用類型值的比較:

var obj3 =  {name:  'hello'}
var obj4 =  {name:  'hello'}
 obj3 === obj4   
 //返回false弹澎,說明二者并不相等

為什么是false?不相等呢殴胧?
放在棧中的變量 obj3团滥、obj4,聲明前置均為undefined拱燃,當(dāng)兩者均被被聲明值的時(shí)候扼雏,是兩個(gè)對(duì)象,引用類型是引用訪問苍蔬,相當(dāng)于在堆中分別開辟了兩個(gè)空間碟绑,堆中會(huì)有對(duì)應(yīng)的屬性+值俺猿,此時(shí)這兩個(gè)對(duì)象在堆中存的便是堆的地址。obj4obj3一樣都開辟了新的堆空間格仲,但是存放的地址也不一樣押袍。判斷obj3是否與obj4相等,看了分析之后凯肋,便知道堆存放的地址并不同谊惭,二者也就不相等

如圖:


image

(3)引用類型的值是同時(shí)保存在棧內(nèi)存和堆內(nèi)存中的對(duì)象

function  sum(){ 
              console.log('sum...')
     }  
var sum2 = sum; 
 sum2()  
//返回sum... 二者是相等的

我們可以就此分析,函數(shù)function sum(),分別有變量sum和函數(shù)對(duì)象代碼(為引用類型侮东,已放在堆中)圈盔。之后sum賦值給sum2悄雅,即sum2事實(shí)上使用的是賦值后sum所指代堆的內(nèi)存地址,即后續(xù)sumsum2共用了堆里的代碼(變量的內(nèi)存地址就像指針一樣驱敲,通過JS自身引擎找到這個(gè)堆),一堆東西起了兩個(gè)不同的名字

如圖:


image

總結(jié): js不同于其他語(yǔ)言宽闲,其不允許直接訪問內(nèi)存中的位置众眨,即不能直接操作對(duì)象的內(nèi)存空間,實(shí)際上容诬,是操作對(duì)象的引用娩梨,所以引用類型的值是按引用訪問的。

準(zhǔn)確地說放案,引用類型的存儲(chǔ)需內(nèi)存的棧區(qū)(棧區(qū)是指內(nèi)存里的棧內(nèi)存)和堆區(qū)(堆區(qū)是指內(nèi)存里的堆內(nèi)存)共同完成姚建,棧區(qū)內(nèi)存保存變量標(biāo)識(shí)符和指向堆內(nèi)存中該對(duì)象的指針,然后吱殉,棧區(qū)內(nèi)存地址也可以說是該對(duì)象在堆內(nèi)存的地址掸冤。

二厘托、引用類型的實(shí)際應(yīng)用

1、函數(shù)的參數(shù)傳遞

第1個(gè)例子:

function  inc(n){ 
          n++; 
        }  
var a =  10; 
 inc(a)
 console.log(a)  
//返回10  

//等同于
 function  inc(){ 
       var n = arguments[0] 
       n++ 
  } 
 //在函數(shù)的一開始將var a = 10賦值進(jìn)var n = arguments[0]稿湿,  //n=arguments[0]=10,此時(shí)與n++為11并沒有返回铅匹,所以與a并無關(guān)系  

var a =  10  
inc(a)
 console.log(a) 
 //返回10

?第2個(gè)例子:

     function  incObj(obj){
     //var obj = o     //0x0001 
       obj.n++ 
        } 
   var o =  {n:  10}    //o = 0x0001  對(duì)其做聲明,為一個(gè)對(duì)象  
   incObj(o)
   console.log(o)  

//等同于  
      function  incObj(){ 
                var obj =arguments[0] 
                 obj.n++  
          } 
 //incObj(o) 相當(dāng)于function incObj(){var obj =arguments[0]饺藤;obj.n++}包斑,
  //可知道obj=arguments[0]=o,相當(dāng)于設(shè)obj為臨時(shí)變量,而o= 0x0001  var o =  {n:  10}  incObj(o) console.log(o)

如圖:


image

總結(jié):
引用類型的本質(zhì)涕俗,變量所存的是這個(gè)對(duì)象的內(nèi)存地址指向堆罗丰,當(dāng)去做賦值時(shí)是把這個(gè)地址進(jìn)行一個(gè)賦值;當(dāng)去訪問的時(shí)候是通過這個(gè)地址去訪問這個(gè)對(duì)象

?第3個(gè)例子:

      function  squireArr( arr ){  
              //var arr = 0x0011  
                 for(var i =  0; i < arr.length; i++){ 
                         arr[i]  = arr[i]  * arr[i]; 
              }
       } 
                 var arr =  [2,1,3,6] 
                 squireArr(arr) 
                 console.log(arr) 
           //(4) [4, 1, 9, 36]

即把function squireArr(arr){}中的數(shù)組squireArr(arr)里的每一項(xiàng)變?yōu)樵瓉淼钠椒皆俟茫磪?shù)arr為數(shù)組里的值萌抵,用for循環(huán)進(jìn)行操作,外界調(diào)用時(shí)元镀,只需調(diào)用一次squireArr(arr)绍填,事實(shí)上數(shù)組squireArr(arr)操作就是對(duì)arr的操作

?第4個(gè)例子:

        function  squireArr2( arr ){ 
                  var newArr =  []; 
                   for(var i =  0; i < arr.length; i++){ 
                              newArr[i]  = arr[i]  * arr[i]; 
                       } 
                        return newArr; 
                   }  
                  var arr2 =  squireArr2(arr) 
                  console.log(arr2)  //返回(4) [16, 1, 81, 1296] 

             arr 
            // (4)  [4,  1,  9,  36] 
arr2 -->  (4)  [16,  1,  81,  1296]

2、對(duì)象的深淺拷貝

針對(duì)這個(gè)例子:

     var obj;  
    var obj2;  
     var obj =  {
              name:  'ruoyu',
              sex:  'male',
              age:  30, 
              friend:  { 
                name:  'hello',
                age:  100 
                   } 
           }  
          var obj2 = obj;

想要?jiǎng)?chuàng)造一個(gè)新的b栖疑,那么就需要遍歷原始a的每一項(xiàng)屬性+值讨永,用來獲取成為新個(gè)體的b所需的東西,并一一對(duì)b進(jìn)行改造遇革,即從一無所有卿闹,改造成與a相似的新個(gè)體,此為克隆澳淑。

如果在遍歷的時(shí)候比原,b這個(gè)新個(gè)體只是遍歷a的前半部分或者局部,那么這稱之為淺拷貝杠巡,如:

      function  shallowCopy(oldObj)  { 
                   var newObj =  {};  
                    for(var i in oldObj)  { 
                        if(oldObj.hasOwnProperty(i))  {
                                newObj[i]  = oldObj[i];  
                         } 
                  }
                return newObj; 
           }

而如果b是遍歷原始a的每一項(xiàng)屬性和值量窘,但是b又是一個(gè)獨(dú)立個(gè)體,與a不相關(guān)氢拥,當(dāng)修改b的時(shí)候蚌铜,a仍然不會(huì)發(fā)生變化,而這叫做深拷貝嫩海,如:

       function  deepCopy(oldObj)  { 
                  var newObj =  {}; 
                   for(var key in oldObj)  { 
                           if(typeof oldObj[key]  ===  'object')  {
                              newObj[key]  =  deepCopy(oldObj[key]); 
                          }else{ 
                             newObj[key]  = oldObj[key]; 
                                    } 
                       } 
                        return newObj;  
                  }

json——string——對(duì)象

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冬殃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子叁怪,更是在濱河造成了極大的恐慌审葬,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異涣觉,居然都是意外死亡痴荐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門官册,熙熙樓的掌柜王于貴愁眉苦臉地迎上來生兆,“玉大人,你說我怎么就攤上這事膝宁⊙荒眩” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵员淫,是天一觀的道長(zhǎng)合蔽。 經(jīng)常有香客問我,道長(zhǎng)满粗,這世上最難降的妖魔是什么辈末? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任愚争,我火速辦了婚禮映皆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘轰枝。我一直安慰自己捅彻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布鞍陨。 她就那樣靜靜地躺著步淹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诚撵。 梳的紋絲不亂的頭發(fā)上缭裆,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音寿烟,去河邊找鬼澈驼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛筛武,可吹牛的內(nèi)容都是我干的缝其。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼徘六,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼内边!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起待锈,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤漠其,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體和屎,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡阳惹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了眶俩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莹汤。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖颠印,靈堂內(nèi)的尸體忽然破棺而出纲岭,到底是詐尸還是另有隱情,我是刑警寧澤线罕,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布止潮,位于F島的核電站,受9級(jí)特大地震影響钞楼,放射性物質(zhì)發(fā)生泄漏喇闸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一询件、第九天 我趴在偏房一處隱蔽的房頂上張望燃乍。 院中可真熱鬧,春花似錦宛琅、人聲如沸刻蟹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)舆瘪。三九已至,卻和暖如春红伦,著一層夾襖步出監(jiān)牢的瞬間英古,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工昙读, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留召调,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓箕戳,卻偏偏與公主長(zhǎng)得像某残,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陵吸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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

  • 從三月份找實(shí)習(xí)到現(xiàn)在玻墅,面了一些公司,掛了不少壮虫,但最終還是拿到小米澳厢、百度环础、阿里、京東剩拢、新浪线得、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,207評(píng)論 11 349
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,090評(píng)論 1 32
  • 2017年9月1日 星期五 雨 朋友圈有曬小朋友的開學(xué)季徐伐,也有曬大學(xué)的開學(xué)季贯钩,讓不想起爸爸送上學(xué)的情景。 沒...
    皇城山茶業(yè)阿娟閱讀 126評(píng)論 0 0
  • 【書籍名稱】 《小說課》[壹] ——折磨讀者的秘密办素。 作者:許榮哲 【閱讀感受】 1角雷,作者選取精彩的小說片段,用來...
    風(fēng)之壹把刀閱讀 299評(píng)論 0 1
  • 內(nèi)容簡(jiǎn)介 初期の代表作「聖伝」のイラスト集です性穿、特に最初の方にある描き下ろしのイラストの綺麗さと言ったら???勺三。た...
    可愛的鹡鸰閱讀 890評(píng)論 7 8