首頁 >web前端 >js教程 >js中深拷貝與淺拷貝的詳細介紹(程式碼分析)

js中深拷貝與淺拷貝的詳細介紹(程式碼分析)

不言
不言原創
2018-08-14 11:25:281012瀏覽

這篇文章帶給大家的內容是關於js中深拷貝與淺拷貝的詳細介紹(程式碼分析) ,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

基本型別& 引用型別

ECMAScript中的資料型別可分為兩種:

基本類型:undefined,null,Boolean,String,Number,Symbol
#引用類型:Object,Array,Date,Function,RegExp等

#不同類型的儲存方式:

基本型別:基本型別值在記憶體中佔據固定大小,保存在堆疊記憶體中
參考型別:參考型別的值是對象,保存在堆內存中,而棧內存存儲的是對象的變量標識符以及對像在堆內存中的存儲地址

不同類型的複製方式:

基本型別

  • 基本型別:從變數到另一個新變數複製基本型別的值,會建立這個值的一個副本,並將該副本複製給新變數

let foo = 1;
let bar = foo;
console.log(foo === bar); // -> true

// 修改foo变量的值并不会影响bar变量的值
let foo = 233;
console.log(foo); // -> 233
console.log(bar); // -> 1
  • 引用類型:從一個變數向另一個新變數複製引用類型的值,其實複製的是指針,最後兩個變數最後都指向同一個物件

let foo = {
  name: 'leeper',
  age: 20
}
let bar = foo;
console.log(foo === bar); // -> true

// 改变foo变量的值会影响bar变量的值
foo.age = 19;
console.log(foo); // -> {name: 'leeper', age: 19}
console.log(bar); // -> {name: 'leeper', age: 19}

深拷貝& 淺拷貝

  • 淺拷貝:僅僅是複製了引用,彼此之間的操作會互相影響

  • 深拷貝:在堆中重新分配內存,不同的地址,相同的值,互不影響

淺拷貝

舉一個例子()

  var me = {
      name: 'zjj',
      age: 19,
      address: {
          home: 'tianjin'
      }
  };
  
  var me_1 = {
      m_token: 'new'
  };
  
  
  function extend(p, c){
      var c = c || {};
      
      for(var i in p) {
          c[i] = p[i];
      }
  }
  extend(me,me_1);

js中深拷貝與淺拷貝的詳細介紹(程式碼分析)

深度拷貝

  var me = {
      name: 'zjj',
      age: 19,
      address: {
          home: 'tianjin'
      }
  };
  
  var me_1 = {
      m_token: 'new'
  };
  
  
  function extend(p, c){
      var c = c || {};
      
      for(var i in p) {
          c[i] = p[i];
      }
  }


  function extendDeeply(p, c) {
    var c = c || {};
      
      for(var i in p) {
        if(typeof p[i] === 'object') {
          // 引用类型需要递归实现深拷贝
          c[i] = (p[i].constructor === Array ) ? [] : {}
          extendDeeply(p[i], c[i]);
        } else {
          // 非引用类型直接复制即可
          c[i] = p[i];
        } 
      }
  }
  extendDeeply(me,me_1);

js中深拷貝與淺拷貝的詳細介紹(程式碼分析)

  • JSON.parse()和JSON.stringify ()

JSON.stringify():把一個js物件序列化為一個JSON字串
JSON.parse():把JSON字串反序列化為一個js物件
let obj = {
  name: 'leeper',
  age: 20,
  friend: {
    name: 'lee',
    age: 19
  }
};
let copyObj = JSON.parse(JSON.stringify(obj));
obj.name = 'Sandman';
obj.friend.name = 'Jerry';
console.log(obj);
// -> {name: "Sandman", age: 20, friend: {age: 19,name: 'Jerry'}}
console.log(copyObj);
// -> {name: "leeper", age: 20, friend: {age: 19,name: 'lee'}}

綜上,JSON.parse()和JSON.stringify()是完全的深拷貝。

動手實現深拷貝 利【遞歸】來實現對物件或陣列的深拷貝。遞歸思路:對屬性中所有引用類型的值進行遍歷,直到是基本型別值為止。

// 深拷贝
function deepCopy(obj) {
  if (!obj && typeof obj !== 'object') {
    throw new Error('error arguments');
  }
  // const targetObj = obj.constructor === Array ? [] : {};
  const targetObj = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    
    //只对对象自有属性进行拷贝
    if (obj.hasOwnProperty(key)) {
      if (obj[key] && typeof obj[key] === 'object') {
        targetObj[key] = deepCopy(obj[key]);
      } else {
        targetObj[key] = obj[key];
      }
    }
  }
  return targetObj;
}

拷貝方式其實也是一種繼承的方式,當然繼承還是有其他方法的!

相關推薦:

js中淺拷貝與深拷貝的簡單介紹以及實作方法

js執行機制的概念? js的執行機制的實作方法

#

以上是js中深拷貝與淺拷貝的詳細介紹(程式碼分析)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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