深淺拷貝與react之immutable.js

不洗碗工做室--nikoumlreact

轉載請標明出處數據結構

深,淺拷貝探究竟

深拷貝和淺拷貝只針對像Object,Array這樣的複雜對象,對於基本的數據類型,則不存在深拷貝和淺拷貝的區別。淺拷貝只是複製了對象的一層屬性,而深拷貝則是遞歸複製了全部的層級。性能

淺拷貝只能拷貝引用,指向的仍是原來的對象,天然也會影響原來的對象。深拷貝則是在堆(數據結構老師講過的哦~)中從新分配了內存,與原來的對象是分隔開的,互不影響。也就是淺拷貝只複製指向某個對象的指針,而不復制對象自己,新舊對象仍是共享同一塊內存。但深拷貝會另外創造一個如出一轍的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。spa

注意基本數據類型,不存在深淺拷貝的區別:指針

let a = 123
let b = a
a = 1234
console.log(a) // 1234
console.log(b) //123
複製代碼

簡單的淺拷貝實現:code

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


 }
   var obj = {
     a: "hello",
     b:{
         a: "world",
         b: 18
       },
     c:["feng", "zheng", "li"],
     d:function() {
         alert("hello world");
       }
   }
   var cloneObj = simpleCopy(obj);
   console.log(cloneObj.b);
   console.log(cloneObj.c);
   console.log(cloneObj.d);
   
   cloneObj.b.a = "changed";
   cloneObj.c = [1, 2, 3];
   cloneObj.d = function() { alert("changed"); };
   console.log(obj.b);
   console.log(obj.c);
   console.log(obj.d);
複製代碼

以上代碼是淺拷貝的簡單實現,以下是運行結果:對象

{ a: 'world', b: 18 }
[ 'feng', 'zheng', 'li' ]
[Function: d]
{ a: 'changed', b: 18 }
[ 'feng', 'zheng', 'li' ]
[Function: d]
複製代碼

另外,使用ES6提供的擴展運算符(...)也能實現淺拷貝:遞歸

let arr1 = [1, 2, 3]
 let arr2 = [...arr1]
 arr1.push(4,5,6)
 console.log(arr1) // [1, 2, 3, 4, 5, 6]
 console.log(arr2) // [1, 2, 3]
複製代碼

簡單的實現深拷貝:內存

主要有JSON.parse()、JSON.stringify(),jQuery的$.extend(true, {}, obj),lodash的_.cloneDeep(obj)和_.clone(obj,true)。字符串

下面以用JSON.stringify把對象轉成字符串,再用JSON.parse把字符串轉成新的對象的方法爲例:

var obj1 = { body: { a: 18 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.body.a = 20;
console.log(obj1);   //{ body: { a: 18 } }
console.log(obj2);   //{ body: { a: 20 } }
複製代碼

React中的深淺拷貝

在React中具備保持state不變的這個原則,是咱們嘗試使用局部更新的方法,這樣能夠有效地提升react的渲染效率。那麼,在保持數據不變性的前提下,咱們怎麼對state進行更新呢?

咱們很容易想到,保持state的不變性應該很簡單吧,只要咱們深複製一個state,而後咱們就獲得了一個clone的state,咱們儘管大膽地對這個clone者作任何操做好了。可是咱們不要忘記了,深拷貝是遞歸複製了原對象的全部的層級,這樣勢必會使操做運行的效率低下,這種方法只是知足了state不變性的原則,可是卻下降程序性能,並無實踐意義。

state的內部數據要變,咱們就建立state的引用,對於不變化的數據,咱們就無需對這個引用作更新。可是在實際操做中深淺拷貝的方式都不夠簡便,因而就有了immutable.js這個專門處理不變性數據的庫來簡化咱們的操做。

舉一個簡單的例子:咱們要「吃雞」

用 chicken/EAT_CHICKEN這個reducer來講明。

運用淺拷貝的reducer:

...
case 'chicken/EAT_CHICKEN':
    newState = Object.assign({}, state, {
        chicken: [
            ...state.chicken.slice(0, action.payload),
            Object.assign({}, state.chicken[action.payload], { isEaten: true }),
            ...state.chicken.slice(action.payload + 1)
        ]
    })
    return newState;
...
複製代碼

運用immutable.js這個庫的reducer:

import { fromJS } from 'immutable';
...
case 'chicken/EAT_CHICKEN':
    return fromJS(state).setIn(['chicken',action.payload,'isEaten'], true).toJS();
...
複製代碼

用了這個庫以後,代碼變得簡潔明瞭,一會兒便輕鬆解決了reducer哦!

相關文章
相關標籤/搜索