首頁 >web前端 >js教程 >什麼是Js中的淺、深拷貝

什麼是Js中的淺、深拷貝

一个新手
一个新手原創
2017-09-09 09:42:221495瀏覽

JavaScript中的淺拷貝與深拷貝

  學了這麼長時間的JavaScript想必大家對淺拷貝和深拷貝還不太熟悉吧,今天在項目中既然用到了,早晚也要理清一下思路了,在了解之前,我們還是先從JavaScript的資料型別存放的位置堆疊開始說起吧!           

#現在我們帶著問題來完成問題。學習!

一:什麼是堆疊?

  我們都知道:在電腦領域中,堆疊是兩種資料結構,它們只能在一端(稱為堆疊頂(top))對資料項目進行插入和刪除。

  • 堆疊:佇列優先,先進先出;由操作系統自動指派釋放 ,存放函數的參數值,局部變數的值等。其操作方式類似於資料結構中的堆疊。

  • 堆:先進後出;動態分配的空間 一般由程式設計師指派釋放, 若程式設計師不釋放,程式結束時可能由OS回收,分配方式倒是類似鍊錶。
    以上都屬於電腦基礎部分,在此都不詳細贅述了,下面我們聯絡JavaScript來剖析一下堆疊。

二:JavaScript中的基本型別與參考型別與堆疊有什麼關聯?

JavaScript的資料型別分為兩大種:
1. 基本型別:Undefined、Null、Boolean、Number 和String,這5中基本資料型別可以直接存取,他們是按照值進行分配的,存放在堆疊(stack)記憶體中的簡單資料段,資料大小確定,記憶體空間大小可以分配。
2. 引用型別:即存放在堆(heap)記憶體中的對象,變數實際保存的是指針,這個指標指向另一個位置。
  以上我們知道了什麼是堆疊,和JavaScript的資料類型,下面我們根據js的資料類型來說明一下他們的拷貝情況:

var obj1 = {name:'bangbang',age:18};
var b = obj1;
var c = obj1.age;

console.log(b.name); //bangbang
console.log(c);      //18//改变b和c的值
b.name = 'yanniu';
c = 22;
console.log(obj1.name);     //yanniu
console.log(obj1.age);       //18

  以上看出:當我們改變b的資料的時候,我們看到了obj1.name的資料也在改變,但是我們改變c的資料的時候發現,obj1.age的值沒有變化,這說明了:b和obj1變數操作的是同一個對象,c和obj1完全獨立的。圖示如下:
什麼是Js中的淺、深拷貝

三:什麼是淺拷貝?

  根據上面的陳述,基本型別拷貝的時候只是在記憶體中又開闢了新的空間,和它的父元素(再次我們稱被拷貝的物件為父元素)屬於互不想幹的東西,因此深淺拷貝是相對於引用類型的,以便於我們對引用類型父物件的保存! 嘿嘿!我們接著看!
例如:

var father1 = {name:'shangdi',age:1000,job:['teacher','cook']};//浅拷贝函数
function copy(obj){    
var childs = {};    
for(var key in obj){
        childs[key] = obj[key];
    }    return childs;
}var child1 = copy(father1);
console.log(child1);    //{ name: 'shangdi', age: 1000 }
console.log(typeof child1); //object

//改变子对象的name属性,发现对父对象的name没有影响 哈哈!
child1.name = 'bangbang';
console.log(father1);   //{ name: 'shangdi', age: 1000 }
console.log(child1);    //{ name: 'bangbang', age: 1000 }
//注意:这次改变子对象的job属性也就是改变数组,//发现对父对象的job竟然有影响,吓死宝宝了,那怎么办呢,那这个copy有什么用呢是吧!
child1.job.push('programer');
console.log(father1);   //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }
console.log(child1);    //{ name: 'shangdi',age: 1000,job: [ 'teacher', 'cook', 'programer' ] }

由上面可分析:淺拷貝的時候,當我們改變子物件的陣列的時候,父物件竟然也跟著改變,也就是說:子物件和父物件在淺拷貝的時候他們指向同一個記憶體的陣列:由圖所示:
什麼是Js中的淺、深拷貝
#    如果我們想要讓子物件的拷貝和父物件沒有一點關聯,那麼我們就必須使用到深度拷貝!嘿嘿!兒子也不能完全跟著爹長啊!

四:什麼是深度拷貝?

深度拷貝就是把父物件拷貝到子物件上,而且兩者的記憶體和以後的運算都互不影響的拷貝!

        function deepCopy(obj){
            var o;            
            switch(typeof obj){            
            case 'undefined': break;            
            case 'string'   : o = obj + '';break;            
            case 'number'   : o = obj - 0;break;            
            case 'boolean'  : o = obj;break;            
            case 'object'   :                
                if(obj === null){
                    o = null;
                }else{                    
                    if(obj instanceof Array){
                        o = [];                        
                        for(var i = 0, len = obj.length; i < len; i++){
                            o.push(deepCopy(obj[i]));
                        }
                    }else{
                        o = {};                        
                        for(var k in obj){
                            o[k] = deepCopy(obj[k]);
                        }
                    }
                }                
                break;            
                default:
                o = obj;break;
            }            
            return o;
        }

什麼是Js中的淺、深拷貝
# 以下是一些克隆的方法供大家參考,不過他們有區別,自己試驗:
方法二:最簡單的

    function deepCopy(obj) {
        return JSON.parse(JSON.stringify(obj));
    }

方法三:

        function deepCopy(obj){
            var newobj, obj;            
            if (obj.constructor == Object){
                newobj = new obj.constructor();
            }else{
                newobj = new obj.constructor(obj.valueOf());//valueOf()方法返回 Array 对象的原始值
            }            
            for(var key in obj){                
                if ( newobj[key] != obj[key] ){                    
                    if ( typeof(obj[key]) == &#39;object&#39; ){
                        newobj[key] = deepCopy(obj[key]);
                    }else{
                        newobj[key] = obj[key];
                    }
                }
            }
            newobj.toString = obj.toString;
            newobj.valueOf = obj.valueOf;            
            return newobj;
        }

方法四:

var cloneObj = function(obj){
    var str, newobj = obj.constructor === Array ? [] : {};    
    if(typeof obj !== &#39;object&#39;){        
    return;
    } else if(window.JSON){
        str = JSON.stringify(obj), //系列化对象
        newobj = JSON.parse(str); //还原
    } else {        
    for(var i in obj){
            newobj[i] = typeof obj[i] === &#39;object&#39; ? 
            cloneObj(obj[i]) : obj[i]; 
        }
    }    return newobj;
};

方法五:(JavaScript物件導向程式設計指南)

    function deepCopy(p,c){
        c = c || {};        
        for (var i in p){            
            if(p.hasOwnProperty(i)){                
            if(typeof p[i] === &#39;object&#39;){
                    c[i] = Array.isArray(p[i]) ? [] : {};
                    deepCopy(p[i],c[i]);
                }else{
                    c[i] = p[i];
                }
            }
        }        return c;
    }

以上是什麼是Js中的淺、深拷貝的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn