我目前正在处理React JS和 React Native构架。在半路上我遇到了不变性或 Immutable-JS library ,当我阅读 Facebook 的 Flux 和 Redux 实现时。
问题是,为什么不变性如此重要?改变对象有什么问题?这不是让事情变得简单吗?
举个例子,让我们考虑一个简单的新闻阅读器应用程序,其打开屏幕是新闻标题的 ListView 。
如果我设置一个对象数组,其值最初,我将无法操作它。这就是不变性原则所说的,对吗? (如果我错了请纠正我。) 但是,如果我有一个必须更新的新新闻对象怎么办?在通常情况下,我可以将对象添加到数组中。 在这种情况下我该如何实现?删除商店并重新创建它? 向数组添加对象不是一个更便宜的操作吗?
最佳答案
我最近一直在研究同一主题。我将尽力回答您的问题并尝试分享我迄今为止所学到的知识。
The question is, why is immutability so important? What is wrong in mutating objects? Doesn't it make things simple?
基本上,这可以归结为这样一个事实:不变性提高了可预测性、性能(间接)并允许突变跟踪。
可预测性
突变隐藏了变化,这会产生(意外的)副作用,从而导致严重的错误。当您强制实现不变性时,您可以保持应用程序架构和思维模型简单,这使得您可以更轻松地推理应用程序。
性能
尽管向不可变对象(immutable对象)添加值意味着需要创建一个新实例,其中需要复制现有值并将新值添加到新对象,这会消耗内存,但不可变对象(immutable对象)可以利用结构共享以减少内存开销。
All updates return new values, but internally structures are shared to drastically reduce memory usage (and GC thrashing). This means that if you append to a vector with 1000 elements, it does not actually create a new vector 1001-elements long. Most likely, internally only a few small objects are allocated.
您可以阅读有关此的更多信息 here .
突变追踪
除了减少内存使用之外,不变性还允许您通过利用引用和值相等来优化应用程序。这使得很容易看出是否有任何变化。例如 react 组件中的状态变化。您可以使用shouldComponentUpdate通过比较状态对象来检查状态是否相同,并防止不必要的渲染。 您可以阅读更多相关信息here .
其他资源:
If I set say an array of objects with a value initially. I can't manipulate it. That's what immutability principle says, right?(Correct me if I am wrong). But, what if I have a new News object that has to be updated? In usual case, I could have just added the object to the array. How do I achieve in this case? Delete the store & recreate it? Isn't adding an object to the array a less expensive operation?
是的,这是正确的。如果您对如何在应用程序中实现这一点感到困惑,我建议您查看如何 redux这样做是为了熟悉核心概念,对我帮助很大。
我喜欢使用 Redux 作为示例,因为它具有不变性。它有一个不可变的状态树(称为store
),其中所有状态更改都是通过分派(dispatch)操作来显式进行的,这些操作由接受先前状态和所述操作(一次一个)的 reducer 处理并返回应用程序的下一个状态。您可以阅读有关其核心原则的更多信息 here .
egghead.io 有一个很棒的 redux 类(class)哪里Dan Abramov redux的作者对这些原理的解释如下(我对代码做了一些修改,以更好地适应场景):
import React from 'react';
import ReactDOM from 'react-dom';
// Reducer.
const news = (state=[], action) => {
switch(action.type) {
case 'ADD_NEWS_ITEM': {
return [ ...state, action.newsItem ];
}
default: {
return state;
}
}
};
// Store.
const createStore = (reducer) => {
let state;
let listeners = [];
const subscribe = (listener) => {
listeners.push(listener);
return () => {
listeners = listeners.filter(cb => cb !== listener);
};
};
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach( cb => cb() );
};
dispatch({});
return { subscribe, getState, dispatch };
};
// Initialize store with reducer.
const store = createStore(news);
// Component.
const News = React.createClass({
onAddNewsItem() {
const { newsTitle } = this.refs;
store.dispatch({
type: 'ADD_NEWS_ITEM',
newsItem: { title: newsTitle.value }
});
},
render() {
const { news } = this.props;
return (
<div>
<input ref="newsTitle" />
<button onClick={ this.onAddNewsItem }>add</button>
<ul>
{ news.map( ({ title }) => <li>{ title }</li>) }
</ul>
</div>
);
}
});
// Handler that will execute when the store dispatches.
const render = () => {
ReactDOM.render(
<News news={ store.getState() } />,
document.getElementById('news')
);
};
// Entry point.
store.subscribe(render);
render();
此外,这些视频更详细地演示了如何实现以下方面的不变性:
关于javascript - 为什么 JavaScript 中的不变性如此重要(或需要)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41989683/