js 深淺拷貝 筆記總結


一、js 數據類型

 javaScritp的數據類型有:數值類型、字符串類型、布爾類型、null、undefined、對象(數組、正則表達式、日期、函數),大致分成兩種:基本數據類型和引用數據類型

     其中:

    (1)基本數據類型:數值、字符串、布爾、null、undefined (值類型)
  (2)復雜(復合)數據類型:對象 (引用類型)

  基本數據類型保存在棧內存,引用類型保存在堆內存中。根本原因在於保存在棧內存的必須是大小固定的數據,引用類型的大小不固定,只能保存在堆內存中,但是可以把它的地址寫在棧內存中以供我們訪問

  如果是基本數據類型,則按值訪問,操作的就是變量保存的值;如果是引用類型的值,我們只是通過保存在變量中的引用類型的地址來操作實際對象

 

舉例:

var a = 1;//定義了一個number類型
var obj1 = {//定義了一個object類型
    name:'obj'
};

 1、基本類型的復制

var a = 1;
var b = a;//復制
console.log(b)//1
a = 2;//改變a的值
console.log(b)//1

賦值的時候,在棧內存中重新開辟內存,存放變量b,所以在棧內存中分別存放着變量a、b各自的值,修改時互不影響

 

 2、引用類型的復制

var color1 = ['red','green'];
var color2 = color1;//復制
console.log(color2)//['red','green'];
color1.push('black') ;//改變color1的值
console.log(color2)//['red','green','black']
color1與color2指向堆內存中同一地址的同一對象,復制的只是引用地址


因此,對於引用類型的復制,簡單賦值無用,需要拷貝。拷貝存在兩種類型:深拷貝與淺拷貝

 

二、深淺拷貝 

淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象
1、淺拷貝
    淺拷貝只是拷貝基本類型的數據,如果父對象的屬性等於數組或另一個對象,那么實際上,子對象獲得的只是一個內存地址,因此存在父對象被篡改的可能,淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存

        var Nation = {  
            nation: '中國'
        };function extendCopy(p) {  
            var c = {};  
            for (var i in p) {    
                c[i] = p[i];  
            }  
            return c;
        }
        var Doctor = extendCopy(Nation);
        Doctor.career = '醫生';
        Doctor.nation = '美國';
        console.log(Doctor.nation); // 美國
        console.log(Nation.nation); // 中國
        console.log(Doctor.career); // 醫生
        console.log(Doctor.__proto_ === Nation.__proto_) // true
     // 這里涉及到使用拷貝父對象的屬性實現繼承

 

        var obj = {
          a: "hello",
          b:{
              a: "world",
              b: 21
            },
          c:["Bob", "Tom", "Jenny"],
          d:function() {
              alert("hello world");
            }
        }
       
        var obj1 = simpleClone(obj);
        console.log('obj1=>>>',obj1);
        // 1、
        obj1.c = ['mm', "Tom", "Jenny"]; // 一層,作為整體,重寫,全改變;改變屬性值,不改變原對象
        console.log('obj=>>>',obj); //obj.c => ["Bob", "Tom", "Jenny"]
     // 2、
   obj1.c[0] = 'mm'; // 淺拷貝時,改變屬性的屬性值,改變原對象
console.log('obj=>>>',obj); //obj.c => ["mm", "Tom", "Jenny"]

 

淺拷貝函數:

       function simpleClone(initalObj) {    
          var obj = {};    
          for ( var i in initalObj) {
            obj[i] = initalObj[i];
          }    
          return obj;
        }

 

2、深拷貝

 深拷貝就是能夠實現真正意義上的數組和對象的拷貝。遞歸調用"淺拷貝"。(深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象)

深拷貝函數:

寫法一:
        function deepClone(initalObj, finalObj) {
            var obj = finalObj || {};
            for (var i in initalObj) {
                var prop = initalObj[i];
          
                // 避免相互引用對象導致死循環,如initalObj.a = initalObj的情況
                if(prop === obj) {
                    continue;
                }
          
                if (typeof prop === 'object') {
                    obj[i] = (prop.constructor === Array) ? [] : {};
                    arguments.callee(prop, obj[i]);
                } else {
                    obj[i] = prop;
                }
            }
            return obj;
        }


寫法二:
        function deepClone(initalObj, finalObj) {
            var obj = finalObj || {};
            for (var i in initalObj) {
                var prop = initalObj[i];
          
                // 避免相互引用對象導致死循環,如initalObj.a = initalObj的情況
                if(prop === obj) {
                    continue;
                }
          
                if (typeof prop === 'object') {
                    obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
                } else {
                    obj[i] = prop;
                }
            }
            return obj;
        }

 

三、深拷貝的應用實例

        // jquery 有提供一個$.extend可以用來做 Deep Copy。
        var $ = require('jquery');
        var obj1 = {
            a: 1,
            b: { f: { g: 1 } },
            c: [1, 2, 3]
        };
        var obj2 = $.extend(true, {}, obj1);
        console.log(obj1.b.f === obj2.b.f);
        // false
        
        // 函數庫lodash,有提供_.cloneDeep用來做 Deep Copy。
        var _ = require('lodash');
        var obj1 = {
            a: 1,
            b: { f: { g: 1 } },
            c: [1, 2, 3]
        };
        var obj2 = _.cloneDeep(obj1);
        console.log(obj1.b.f === obj2.b.f);
        // false

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM