不洗碗工做室--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中具备保持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哦!