javascript實現引用數據類型的深拷貝和淺拷貝詳解
阿新 • • 發佈:2019-02-01
var struct blue name 拷貝 ont javascrip ceo ole
關於引用類型值的詳解,請看另一篇隨筆 https://www.cnblogs.com/jinbang/p/10346584.html
深拷貝和淺拷貝,也就是引用數據類型棧和堆的知識點。深淺拷貝的原型都是Object,深拷貝指向的棧內存不一樣,淺拷貝指向的棧內存一樣): 如何區分深拷貝與淺拷貝,就是假設B復制了A,當修改A時,看B是否會發生變化,如果B沒有發生變化,說明是深拷貝。如果B也跟著發生了變化,說明是淺拷貝。
let obj = { name: "jin", arr: ["red","blue","black"]}; let obj1 = {}; Object.defineProperties(obj1, Object.getOwnPropertyDescriptors(obj));// 深拷貝 Object.assign(obj1, obj); // 深拷貝 obj1 = JSON.parse(JSON.stringify(obj)); // 深拷貝 obj1 = deepCopy(obj); // 使用到深拷貝函數 obj1 = obj; // 淺拷貝 obj1 = Object.assign(obj); // 淺拷貝
下面是deepCopy()深拷貝函數,其中使用到了判斷變量的類型函數
// 判斷變量的類型 function getType(obj){ let str = Object.prototype.toString.call(obj); //檢測基本類型值,引用類型值的類型 let map = { ‘[object Boolean]‘: ‘boolean‘, ‘[object Number]‘: ‘number‘, ‘[object String]‘: ‘string‘, ‘[object Function]‘: ‘function‘, ‘[object Array]‘: ‘array‘, ‘[object Date]‘: ‘date‘, ‘[object RegExp]‘: ‘regExp‘,‘[object Undefined]‘: ‘unfefined‘, ‘[object Null]‘: ‘null‘, ‘[object Object]‘: ‘object‘ }; if(obj instanceof Element){ return ‘element‘; } return map[str]; } // 深拷貝函數 function deepCopy(p){ let obj; let str = getType(p); if(str === ‘array‘){ obj = []; for(let i=0;i<p.length;i++){ // obj.push(p[i]); // 不能這樣寫,因為會把array的堆內存也會復制過去 obj.push(arguments.callee(p[i])); //回調自己 } }else if(str === ‘object‘){ obj = {}; for(let i in p){ // obj[i] = p[i]; // 不能這樣寫,因為會把object的堆內存也會復制過去 obj[i] = arguments.callee(p[i]); //回調自己 } } else { return p; } return obj; }
需要特別註意的是,使用JSON.parse(JSON.stringify(x))不是一個很好的選擇,也算是它們的坑吧:
對象是由構造函數生成的:會丟棄對象的constructor,因為JSON.stringify()只能序列化對象的可枚舉的自有屬性 時間對象:變成字符串 RegExp,Error對象:變成空對象 函數,undefined:會被丟失 NaN,Infinity和-Infinity:變成nullfunction Person(name){ this.name = name; } var person = new Person(‘liai‘); var test = { name: ‘jin‘, person: person, //對象是由構造函數生成的:會丟棄對象的constructor date: new Date(), //序列化後返回是字符串,不是時間對象 regexp: new RegExp(‘\\w+‘), //序列化後返回空對象:{} err: new Error(), //序列化後返回空對象:{} fun: function(){}, //序列化後會丟失 undef: undefined, //序列化後會丟失 nun: NaN, //序列化後返回null }; console.log(test); console.log(JSON.parse(JSON.stringify(test)));
javascript實現引用數據類型的深拷貝和淺拷貝詳解