1. 程式人生 > 其它 >淺拷貝 & 深拷貝

淺拷貝 & 深拷貝

技術標籤:Javascriptjavascripttypescripthtml5es6前端

淺拷貝:僅僅是指向被拷貝的記憶體地址,如果原地址中物件被改變了,那麼淺拷貝出來的物件也會相應改變。

深拷貝:在計算機中開闢了一塊新的記憶體地址用於存放複製的物件。
// 淺拷貝
var sourceObj = {
  name: 'tt',
  age: 18,
  job: 'web',
  friends: ['t1', 't2']
}

function cloneObj(sourceObj) {
  var targetObj = {}
  for (var prop in sourceObj)
{ if (sourceObj.hasOwnProperty(prop)) { targetObj[prop] = sourceObj[prop] } } return targetObj } var targetObj = cloneObj(sourceObj)
// 淺拷貝
    var obj = {
         num:1,
         array : ['miss', 'alias']
     }
    function shallowCopy(object) {
       var map = {};
       for (
var i in object) { map[i] = object[i]; } return map; } var newObj = shallowCopy(obj) newObj.name = '小米' newObj.array.push('wuli') console.log(newObj) //{ ["miss", "alias", "wuli"], name: "小米", num: 1} console.log(obj)//{ ["miss", "alias", "wuli"], num: 1}
var a = {name:1, sya:function(){ console.log("列印")},age:undefined}; //{name:1,sya:f}
var b = JSON.parse(JSON.stringify(a)); // {name:1}
// MDN給出的解釋:undefined、function、symbol 會在轉換過程中被忽略。
// 深拷貝
var sourceObj = {
  name: 'tt',
  age: 18,
  job: 'web',
  friends: ['t1', 't2']
}

// util作為判斷變數具體型別的輔助模組
var util = (function() {
  var class2Type = {}
  var objTypes = ["Null","Undefined","Number","Boolean","String","Object","Function","Array","RegExp","Date”]

  objTypes.forEach(function(item) {
    class2Type['[object ' + item + ']'] = item.toLowerCase()
  })

  function isType(obj, type) {
    return getType(obj) === type
  }

  function getType(obj) {
    return class2type[Object.prototype.toString.call(obj)] || 'object'
  }

  return {
    isType: isType,
    getType: getType
  }
})()


// deep引數用來判斷是否是深度複製
function copy(obj, deep){
  // 如果obj不是物件,那麼直接返回值就可以了
  if(obj == null || typeof obj !== 'object'){
    return obj
  }

  // 定義需要的區域性變數,根據obj的型別來調整target的型別
   var i,
   target = util.isType(obj,"array") ? [] : {},
   value,
   valueType

   for(i in obj){
        value = obj[i]
        valueType = util.getType(value)
   // 只有在明確執行深複製,並且當前的value是陣列或物件的情況下才執行遞迴複製
        if(deep && (valueType === "array" || valueType === "object")){
            target[i] = copy(value)
        }else{
            target[i] = value
        }
    }
    return target
}

var targetObj = copy(sourceObj, true);
targetObj.friends.push ('t3');
console.log(sourceObj) // ['t1', 't2']
// 深拷貝
Object.prototype.clone = function() {
  var Constructor = this.constructor
  var obj = new Constructor()
  for (var attr in this) {
    if (this.hasOwnProperty(attr)) {
      if (typeof this[attr] !== 'function') {
        if (this[attr] === null) {
          obj[attr] = null
        } else {
          obj[attr] = this[attr].clone()
        }
      }
    }
  }
  return obj
}
/* Method of Array*/
Array.prototype.clone = function() {
  var thisArr = this.valueOf()
  var newArr = []
  for (var i = 0; i < thisArr.length; i++) {
    newArr.push(thisArr[i].clone())
  }
  return newArr
}
/* Method of Boolean, Number, String*/
Boolean.prototype.clone = function() {
  return this.valueOf()
}
Number.prototype.clone = function() {
  return this.valueOf()
}
String.prototype.clone = function() {
  return this.valueOf()
}
/* Method of Date*/
Date.prototype.clone = function() {
  return new Date(this.valueOf())
}
/* Method of RegExp*/
RegExp.prototype.clone = function() {
  var pattern = this.valueOf()
  var flags = ''
  flags += pattern.global ? 'g' : ''
  flags += pattern.ignoreCase ? 'i' : ''
  flags += pattern.multiline ? 'm' : ''
  return new RegExp(pattern.source, flags)
}
function deepClone(source){
  // 判斷複製的目標是陣列還是物件
  const targetObj = source.constructor === Array ? [] : {}; 
  for(let keys in source){ // 遍歷目標
    if(source.hasOwnProperty(keys)){
      if(source[keys] && typeof source[keys] === 'object'){ 
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys]);
      }else{ // 如果不是,就直接賦值
        targetObj[keys] = source[keys];
      }
    } 
  }
  return targetObj;
}
//測試一下
var a = {name:1, sya:function(){ console.log("列印")},age:undefined}; 
var b = deepClone(a);
b.name=2;
console.log(a)//{name:1,sya:f,age:undefined}
console.log(b)//{name:2,sya:f,age:undefined}
// 練習題1
var a = {n: 1}  
var b = a;  
a.x = a = {n: 2}  
console.log(a.x);  // undefined
console.log(b.x);  // {n: 2}
// 練習題2
var a = {n: 1}  
var b = a;  
b.n = a.f = {n: 2};
console.log(a);  // {n:{n:2},f:{n:2}}
console.log(b);  // {n:{n:2},f:{n:2}}