深复制与浅复制
let obj = {
a: 1,
arr: [1, 2]
};
let obj1 = obj; //浅复制
obj1.a = 2
console.log(obj) // { a:2, arr: [1,2] };
//一样的体式格局
let obj = {
a: 1,
arr: [1, 2]
};
let obj2 = deepCopy(obj); //深复制
obj2.a = 2
console.log(obj) // { a:1, arr: [1,2] };
因为JavaScript存储对象都是存地点的,所以浅复制会致使 obj 和 obj1
指向一致块内存地点,也许的示意图以下。而深复制平常都是拓荒一块新的内存地点,将原对象的各个属性逐一复制出去。
es6-Object.assign()要领
深复制只要一层,之后为浅复制(除非再次运用Object.assign嵌套体式格局赋值)
let obj = {
a: 1,
arr: [1, 2]
};
let obj1 = Object.assign({}, obj);
obj1.a = 2
//稳定
console.log(obj) // { a:1, arr: [1,2] };
let obj = {
a: {
b: 20
},
arr: [1, 2]
};
let obj1 = Object.assign({}, obj);
obj1.a.b = 2;
//除非再次运用Object.assign嵌套体式格局赋值
//变化
console.log(obj) // { a:{b:2}, arr: [1,2] };
为何运用不可变(immutable)的数据?
(pureRender连系immutable,见末端)
下面是项目中现实的一个例子
第一种体式格局
//recduer.js(cart)第一种体式格局
case types.CART_PUT_MAIN + '_SUCCESS':
//更新数据
carts = state.main.carts; // carts 选中的id数组
id = action.param.id;
newState = {
...state,
main:{
...state.main,
itemObj:{
...state.main.itemObj,
[id]:{
...state.main.itemObj[id],
quantity:action.param.quantity
}
}
}
};
sum = sumCommon(carts, newState.main.itemObj);
newState = {
...newState,
main:{
...newState.main,
...sum
}
};
return newState;
让我们来看一下对数据层的变化:
componentWillReceiveProps(nextProps){
console.log(nextProps);
//next:望文生义是接收到的next->props,输出的是上面要领中的newState的值
console.log(this.props);
//cur:是当前的props的值,因为运用的是类immutable的体式格局,所以数据稳定;
}
第二种体式格局
//recduer.js(cart)第一种体式格局
case types.CART_PUT_MAIN + '_SUCCESS':
newState = Object.assign({}, state);
carts = newState.main.carts; // carts 选中的id数组
id = action.param.id;
//浅复制
newState.main.itemObj[id].quantity = action.param.quantity;;
sum = sumCommon(carts, newState.main.itemObj);
newState = Object.assign({}, newState, {
main: Object.assign({}, newState.main, sum)
});
return newState;
让我们来再来看一下对数据层的变化:
componentWillReceiveProps(nextProps){
console.log(nextProps);
//next:望文生义是接收到的next->props,输出的是上面要领中的newState的值
console.log(this.props);
//cur:是当前的props的值,而这个因为浅复制,这个值被转变了
}
为了让数据变化越发可测,我们应该运用深复制相干,让我们本身的数据越发平安
处置惩罚要领一:es7 … 的体式格局
直接{…obj}赋值属于浅复制,在修正值时{…obj,a:1}就起到了类深复制的结果
更新一个 Object ,则:
let obj = {
a: 0,
b: 20,
}
obj = {...obj, a: obj.a + 1}
而不是:
obj.a = obj.a + 1
一样的为了防止对 Object 的 in-place editing,数组也是一样:
let arr = [
{ id: 1,a: 1}
]
arr = [...arr, { id: 2,a: 2} ]
而不是:
let arr = [
{ id: 1, a:1}
]
arr.push({ id: 2, a,2});
以如许的体式格局,无需 Immutable.js ,我们能够让运用程序状况是 不可变(Immutable) 的。
…注意事项及请求
let obj = {
a: 20,
arr: [1, 2]
};
let obj1 = { ...obj }; //于obj1=obj一样
// 坚持一致,只管不要运用如许的替代(有能够形成不必要的贫苦)
obj1.a = 2
//...只管运用如许的赋值情势
obj1 = { ...obj1 , a:2 }
//深复制
console.log(obj) // { a:20, arr: [1,2] };
console.log(obj1) // { a:2, arr: [1,2] };
…与Object.assign属于一个原理(这里和层级相干)
//你能够将其转化为
let obj = {
a: {
b: 20
},
arr: [1, 2]
};
let obj1 = obj
obj1 = Object.assign({}, obj1, {
a: Object.assign({}, obj1.a,{b:2})
});
console.log(obj) //{ a:{b:20}, arr: [1,2] }
console.log(obj) //{ a:{b:2}, arr: [1,2] }
所以只管运用...替代Object.assign
处置惩罚要领二:运用immutable.js
为何须要运用immutable.js
之前体式格局的多层嵌套
//深复制(类immutable)
newState = {
...state,
main:{
...state.main,
itemObj:{
...state.main.itemObj,
[id]:{
...state.main.itemObj[id],
prop:action.param.props_str,
product_id:action.param.product_id,
price:action.param.price
}
}
}
};
//浅复制
newState.main.itemObj[id].prop = action.param.props_str;
//immutable.js体式格局
...参考immutable的api吧,临时就不供应了--!
PureRenderMixin运用请参考以下内容
简朴的说就是数据变化,比较前后两次的数据是不是雷同,推断是不是从新render;不然你的父容器一转变数据,一切的子组件都从新衬着了,为了增添机能请运用pureRender;
(封装好的PureRender以下:)
'use strict';
import { is } from 'immutable';
let hasOwnProperty = Object.prototype.hasOwnProperty;
function shallowEqual(objA, objB) {
if (objA === objB || is(objA, objB)) {
return true;
}
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
return false;
}
let keysA = Object.keys(objA);
let keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
let bHasOwnProperty = hasOwnProperty.bind(objB);
for (let i = 0; i < keysA.length; i++) {
if (!bHasOwnProperty(keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
return false;
}
}
return true;
}
function shallowCompare(instance, nextProps, nextState) {
return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState);
}
function shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}
function pureRenderDecorator(component) {
component.prototype.shouldComponentUpdate = shouldComponentUpdate;
}
module.exports = pureRenderDecorator;
/*运用体式格局*/
import pureRender from 'pure-render-decorator';
//babel设置中引入一个transform-decorators-legacy插件
@pureRender
class XXX extends React.Component {
//...
}
PureRender的运用请求:关于子组件须要什么参数通报什么,不要把一大块无用的数据引入,不然两次传入的this.props能够始终会不一样,致使PureRender无效