引用類型對(duì)象拷貝

引用類型與非引用類型

ECMA Script中規(guī)定,javascript的基本數(shù)據(jù)類型分為兩類,即基本數(shù)據(jù)類型和引用類型,其中基本數(shù)據(jù)類型包括5樣,number、string 、boolean、以及undefined、null兩個(gè)特殊類型,其次引用類型包括狹義的Object、Array、Function、正則等.

關(guān)于這兩種數(shù)據(jù)類型,他們的不同之處在于數(shù)據(jù)的保存的形式不同,對(duì)于基本類型的數(shù)據(jù),其保存的方式是在內(nèi)存中的棧空間,開辟一個(gè)固定大小的空間進(jìn)行固定位置的保存,并且數(shù)據(jù)的訪問形式是后進(jìn)先出,而引用類型的數(shù)據(jù),其保存的形式是在內(nèi)存的堆空間開辟一個(gè)動(dòng)態(tài)的空間保存來保存數(shù)據(jù)的值(因?yàn)閿?shù)據(jù)的大小不固定),當(dāng)我們?cè)L問這個(gè)變量的時(shí)候其實(shí)是根據(jù)出存在棧空間的指針尋址來查找到相應(yīng)的堆內(nèi)存空間,這也就很好地解釋了為什么,當(dāng)我們給基本類型進(jìn)行重復(fù)賦值的時(shí)候,基本數(shù)據(jù)的值不會(huì)改變,而引用類型會(huì)一起連帶改變,因?yàn)槲覀兊母淖儾辉偈菃为?dú)去創(chuàng)建一個(gè)副本,而是查找了同一個(gè)指針引用并改變了其堆內(nèi)存中的值 。

(string類型有些特殊,因?yàn)樽址哂锌勺兊拇笮。燥@然它不能被直接存儲(chǔ)在具有固定大小的變量中。由于效率的原因,我們希望JS只復(fù)制對(duì)字符串的引用,而不是字符串的內(nèi)容。但是另一方面,字符串在許多方面都和基本類型的表現(xiàn)相似,而字符串是不可變的這一事實(shí)(即沒法改變一個(gè)字符串值的內(nèi)容),因此可以將字符串看成行為與基本類型相似的不可變引用類型。
)

如下代碼輸出結(jié)果及原因

var obj1 = {a:1, b:2};
var obj2 = {a:1, b:2};
console.log(obj1 == obj2);//兩個(gè)不同的對(duì)象儲(chǔ)存的是不同的指針。false
console.log(obj1 = obj2);//將obj2賦值給obj1,就是對(duì)指針進(jìn)行復(fù)制,那么兩者的指針指向同一個(gè)堆內(nèi)存空間.
console.log(obj1 == obj2);//兩個(gè)對(duì)象的指針是相同的,指向同一個(gè)內(nèi)存空間。ture

如下代碼輸出結(jié)果及原因

var a = 1
var b = 2
var c = { name: '饑人谷', age: 2 }
var d = [a, b, c]

var aa = a
var bb = b
var cc = c
var dd = d

a = 11
b = 22
c.name = 'hello'//改變c.name的值
d[2]['age'] = 3  //改變c.age的值

console.log(aa) //會(huì)輸出1
console.log(bb) //會(huì)輸出2,都是值傳遞,aa和a,bb和吧b都會(huì)開辟一個(gè)塊屬于自己的棧空間
console.log(cc)//會(huì)輸出{ name: 'hello', age: 3 }對(duì)象的賦值是引用傳遞,cc和c都是指向同一塊堆內(nèi)存。
console.log(dd)//會(huì)輸出[ 11, 22, { name: 'hello', age: 3 } ]數(shù)組的賦值也是引用傳遞

如下代碼輸出結(jié)果及原因

var a = 1
var c = { name: 'jirengu', age: 2 }

function f1(n){
  ++n
}
function f2(obj){
  ++obj.age
}

f1(a)  //1 ,會(huì)默認(rèn)執(zhí)行賦值動(dòng)作,var n = a,屬于值傳遞,++n時(shí),a依舊保持原始值不變的
f2(c)  //會(huì)默認(rèn)執(zhí)行var obj = c;這時(shí)候它們都是指向同一塊堆內(nèi)存,當(dāng)執(zhí)行++obj.age時(shí),對(duì)象c的age屬性加一,所以這個(gè)時(shí)候c = {name:'jirengu',age:3}
f1(c.age) //取出c.age = 3 默認(rèn)執(zhí)行var n = 3.不會(huì)影響c.age
console.log(a) //會(huì)輸出1
console.log(c)//會(huì)輸出{ name: 'jirengu', age: 3 }

過濾如下數(shù)組,只保留正數(shù),直接在原數(shù)組上操作

var arr = [3,1,0,-1,-3,2,-5]
function filter(arr){
    for (var i=0; i<arr.length; i++) {
        if (arr[i] <= 0) {
            arr.splice(i,1); //當(dāng)有一個(gè)數(shù)被刪除時(shí),下一個(gè)數(shù)的index就變成了現(xiàn)在的這個(gè)值。如果繼續(xù)循環(huán)就會(huì)錯(cuò)過下一個(gè)元素
            i--;
        }
    }
}
filter(arr)
console.log(arr) // [3,1,2]

過濾如下數(shù)組,只保留正數(shù),原數(shù)組不變,生成新數(shù)組

var arr = [3,1,0,-1,-3,2,-5]
function filter(arr){
var newArr = []; 
var j = 0;
    for (var i=0; i<arr.length; i++) {
        if (arr[i] > 0 ) {
            newArr[j] = arr[i];
            j++;
        }
    }
    return newArr;
}
var arr2 = filter(arr)
console.log(arr2)
console.log(arr)

寫一個(gè)深拷貝函數(shù),用兩種方式實(shí)現(xiàn).

深拷貝指的是,當(dāng)我們重新給引用類型賦值到一個(gè)新的變量的時(shí)候,其所賦值的內(nèi)容不再是簡(jiǎn)單的將地址進(jìn)行拷貝,而是另外創(chuàng)建了一個(gè)棧空間,并用于保存新值的地址,這樣當(dāng)我們?nèi)ジ淖冊(cè)家玫刂返膶傩灾禃r(shí),并不會(huì)影響后續(xù)新賦值的引用類型的值,其核心思想是使用遞歸,并遞歸至基本類型變量后,再?gòu)?fù)制。

淺拷貝示例:

var obj = {
    name:'abc',
    friend:{
        name:'def',
        sex:'female'
    }
}
function shadowCopy(obj) {
    var newObj = {};
    for (var key in obj) {
        //每一項(xiàng)直接賦值,如果是引用類型就會(huì)出問題
        newObj[key] = obj[key];
    }
   return newObj;
}
var obj2 = shadowCopy(obj);
obj2.name = 'ghi';
console.log(obj);
obj2.friend.name = 'jkl';
console.log(obj);
//改變非引用類型的時(shí),原對(duì)象不會(huì)發(fā)生變化。但是如果有引用類型時(shí)就會(huì)影響,所以需要深拷貝

深拷貝示例1

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

深拷貝示例2

//利用json.stringify()將對(duì)象轉(zhuǎn)換為字符串,然后再利用json.parse()將字符串轉(zhuǎn)換為對(duì)象
function deepCopy1(obj) {
    return newObj = JSON.parse(JSON.stringify(obj));
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,940評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,170評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評(píng)論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評(píng)論 1 280
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評(píng)論 2 370

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

  • 引用類型 引用類型變量保存的僅僅是一個(gè)指針,指針指向堆內(nèi)存中保存對(duì)象的位置。 所以基本類型復(fù)制的時(shí)候僅僅復(fù)制值,復(fù)...
    DeeJay_Y閱讀 582評(píng)論 0 0
  • 1.引用類型有哪些?非引用類型有哪些非引用類型值,即基本類型值(數(shù)值,布爾值,undefined,null):指保...
    青鳴閱讀 411評(píng)論 0 0
  • 1.引用類型有哪些?非引用類型有哪些 引用類型包括:數(shù)組、對(duì)象、正則、函數(shù) 非引用類型(即基本類型):數(shù)值、布爾值...
    饑人谷_js_chen閱讀 273評(píng)論 0 0
  • 1.引用類型有哪些?非引用類型有哪些引用類型:對(duì)象、數(shù)組、函數(shù)、正則。變量中保存的是指向存儲(chǔ)數(shù)據(jù)內(nèi)容位置的指針非引...
    lingfighting閱讀 216評(píng)論 0 0
  • 1.引用類型; 2.過濾數(shù)組; 3.深淺拷貝方法; 1.引用類型有哪些?非引用類型有哪些 引用類型:引用類型(Ob...
    好奇而已閱讀 1,373評(píng)論 0 0