深刻理解javaScript的深複製和淺複製

javascript有五種基本數據類型(也就是簡單數據類型),它們分別是:Undefined,Null,Boolean,Number和String。還含有一種複雜數據類型,就是對象javascript

注意Undefined和Null的區別,Undefined類型只有一個值,就是undefined,Null類型也只有一個值,也就是null
Undefined其實就是已聲明未賦值的變量輸出的結果
null其實就是一個不存在的對象的結果css

var c;
console.log(c)//undefined

console.log(document.getElementById('wsscat'))//沒有id爲wsscat的節點,輸出null

簡單的數據類型和複雜的數據類型有如下重要的區別java

對於簡單數據類型

它們值在佔據了內存中固定大小的空間,並被保存在棧內存中。當一個變量向另外一個變量複製基本類型的值,會建立這個值的一個副本,還有就是不能給基本數據類型的值添加屬性git

var a = 1;
var b = a;
a.attr = 'wsscat';
console.log(a.attr)//undefined

上面代碼中a就是簡單數據類型(Number),b就是a的副本,它們二者都佔有不一樣位置但相等的內存空間github

對於複雜的數據類型

複雜的數據類型即引用類型,它的值是對象,保存在堆內存中,包含引用類型值的變量實際上包含的並非對象自己,而是一個指向該對象的指針。從一個變量向另外一個變量複製引用類型的值,複製的實際上是指針,所以兩個變量最終都指向同一個對象。數組

var obj = {
            name:'wsscat',
            age:0
        }
        var obj2 = obj;
        obj2['c'] = 5;
        console.log(obj);//Object {name: "wsscat", age: 0, c: 5}
        console.log(obj2);////Object {name: "wsscat", age: 0, c: 5}

qq20161016-0

咱們能夠看到obj賦值給obj2後,當咱們更改其中一個對象的屬性值,兩個對象都發生了改變,究其緣由局勢由於obj和obj2這兩個變量都指向同一個指針,賦值只是複製了指針,因此當咱們改變其中一個的值就會影響另一個變量的值函數

淺拷貝

其實這段代碼就是淺拷貝,有時候咱們只是想備份數組,可是隻是簡單讓它賦給一個變量,改變其中一個,另一個就緊跟着改變,但不少時候這不是咱們想要的指針

var obj = {
            name:'wsscat',
            age:0
        }
        var obj2 = obj;
        obj2['c'] = 5;
        console.log(obj);//Object {name: "wsscat", age: 0, c: 5}
        console.log(obj2);////Object {name: "wsscat", age: 0, c: 5}

深拷貝

數組
對於數組咱們可使用slice()concat()方法來解決上面的問題
slicecode

var arr = ['wsscat', 'autumns', 'winds'];
        var arrCopy = arr.slice(0);
        arrCopy[0] = 'tacssw'
        console.log(arr)//['wsscat', 'autumns', 'winds']
        console.log(arrCopy)//['tacssw', 'autumns', 'winds']

concat對象

var arr = ['wsscat', 'autumns', 'winds'];
        var arrCopy = arr.concat();
        arrCopy[0] = 'tacssw'
        console.log(arr)//['wsscat', 'autumns', 'winds']
        console.log(arrCopy)//['tacssw', 'autumns', 'winds']

對象
對象咱們能夠定義一個新的對象並遍歷新的屬性上去實現深拷貝

var obj = {
            name:'wsscat',
            age:0
        }

        var obj2 = new Object();
        obj2.name = obj.name;
        obj2.age = obj.age

        obj.name = 'autumns';
        console.log(obj);//Object {name: "autumns", age: 0}
        console.log(obj2);//Object {name: "wsscat", age: 0}

固然咱們能夠封裝好一個方法來處理對象的深拷貝,代碼以下

var obj = {
            name: 'wsscat',
            age: 0
        }
        var deepCopy = function(source) {
            var result = {};
            for(var key in source) {
                if(typeof source[key] === 'object') {
                    result[key] = deepCopy(source[key])
                } else {
                    result[key] = source[key]
                }
            }
            return result;
        }
        var obj3 = deepCopy(obj)
        obj.name = 'autumns';
        console.log(obj);//Object {name: "autumns", age: 0}
        console.log(obj3);//Object {name: "wsscat", age: 0}
 

在javascript中函數也是一種數據,可以像操做一個對象對它進行操做。而且javascript不進行數據類型檢查,數組能夠存聽任何東西,在下面代碼中咱們不但在數組中存放了函數,而且也能夠在存放一個執行函數的返回值,因此數組前兩個數據存放都是函數執行返回值

var funcA = function() {
            console.log("funcA");
            return "hello funA";
        }
        var funcB = function() {
            console.log("funcB");
            return "hello funB";
        }
        var funcC = function() {
            console.log("funcC");
            return "hello funC";
        }
        var arr = [funcA(), funcB(), funcC];
        console.log(arr);
        arr[2]();
輸出的結果以下
qq20161105-0
相關文章
相關標籤/搜索