最近在開發中遇到一個小問題,就是因爲js的淺拷貝致使變量被污染,忽然發現對於js的變量值傳遞和引用傳值並無特別注意,現在總結以下,以備來者考慮。es6
JS的變量分普通類型和引用類型,具體以下:ui
基本數據類型:String,Boolean,Number,Undefined,Null;spa
引用數據類型:Object(Array,Date,RegExp,Function);prototype
對於普通類型的變量賦值都是值傳遞,而引用類型變量的賦值。例以下面的代碼:指針
var b = 3; var c = b; b = 2; console.log(b); // 2 console.log(c); // 3
普通的數據類型變量的賦值,只是值傳遞,變量之間互不影響。而引用類型不一樣:code
var MyObj = { price: "200.00", count: 24 }; var Gift = MyObj; MyObj.price = "300.00"; console.log(Gift.price); // 300.00 console.log(MyObj.price); // 300.00
因此這種引用類型變量的複製是被稱爲淺拷貝:新變量的指針指向被複制的變量,當被複制的變量發生變化,新變量也會隨着改變。而咱們工做實際中是須要徹底拷貝一個變量,一個完整備份,這就是深拷貝。blog
簡單來講,深淺拷貝的原理圖以下:遞歸
因此問題來了,怎麼才能實現深拷貝的。開發
兩種途徑,一種本身使用遞歸的方式去作深拷貝,一種使用第三方庫或者es原生實現。io
es6的方式最簡單,結合遞歸代碼以下:
// 遞歸方式實現深拷貝 function DeepCopy(obj) { var return_obj = {}; for (let key in obj) { if (Object.prototype.toString.call(obj[key]) === '[Object Object]') { return_obj[key] = DeepCopy(obj[key]); } else { return_obj[key] = {...obj[key]}; // es6語法糖,處理當前層次賦值爲深拷貝 } } return return_obj; }
第三方庫能夠使用loadash
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