为什么不变性在JavaScript中如此重要(或需要)?

我目前正在研究React JS和React本机框架。在中途,当我读到Facebook的Flux和Redux实现时,我遇到了不变性或不变性JS库

问题是,为什么不变性如此重要?变异对象有什么错?这不是让事情变得简单吗

给出一个例子,让我们考虑一个简单的新闻阅读器 app,打开屏幕是新闻标题的列表视图。

如果我将对象数组设置为,初始值为,则无法对其进行操作。这就是不变性原则所说的,对吗?(如果我错了,请纠正我。)
但是,如果我有一个必须更新的新新闻对象呢?在通常情况下,我可以将对象添加到数组中。
在这种情况下,我如何实现目标?是否删除存储并重新创建它?
向数组中添加对象不是一种成本较低的操作吗

我最近一直在研究同一个话题。我会尽我所能回答你的问题,并尝试分享到目前为止我所学到的东西

问题是,为什么不变性如此重要?这有什么问题吗
变异对象?这不是让事情变得简单吗

基本上,它归结为一个事实,即不变性增加了可预测性、性能(间接地),并允许进行突变跟踪

可预测性

突变隐藏了变化,这会产生(意想不到的)副作用,从而导致讨厌的bug。当您强制实施不变性时,您可以保持应用程序体系结构和心智模型的简单,从而更容易对应用程序进行推理

性能

即使向不可变对象添加值意味着需要创建一个新实例,其中需要复制现有值,并且需要向新对象添加新值,这会消耗内存,但不可变对象可以利用结构共享来减少内存开销

所有更新都返回新值,但内部结构共享给
大幅减少内存使用(和GC抖动)。这意味着如果
如果附加到一个包含1000个元素的向量,它实际上不会创建
一个新的向量1001个元素长。最有可能的是,内部只有几个
分配小对象

你可以在这里了解更多

突变跟踪

除了减少内存使用外,不变性还允许您通过使用引用和值相等来优化应用程序。这使我们很容易看到是否有任何变化。例如,react组件中的状态更改。您可以使用shouldComponentUpdate通过比较状态对象来检查状态是否相同,并防止不必要的渲染。
你可以在这里了解更多

额外资源:

  • 不变性之道
  • 不变的数据结构和JavaScript
  • JavaScript中的不变性

如果我设置了一个数组,首先是一个值为的对象数组。我不能
操纵它。这就是不变性原理所说的,对吗
如果我错了,请告诉我。但是,如果我有一个新的新闻对象
要更新吗?在通常情况下,我可以将对象添加到
大堆在这种情况下,我如何实现目标?删除商店&重现它?
向数组中添加对象不是一种成本较低的操作吗

是的,这是正确的。如果您对如何在应用程序中实现这一点感到困惑,我建议您了解redux是如何做到这一点的,以熟悉核心概念,这对我有很大帮助

我喜欢以Redux为例,因为它包含不变性。它有一个单一的不可变状态树(称为存储),其中所有状态更改都是通过调度操作显式进行的,这些操作由一个reducer处理,reducer接受上一个状态和所述操作(一次一个)并返回应用程序的下一个状态。你可以在这里阅读更多关于它的核心原则

在egghead.io上有一个很好的redux课程,redux的作者Dan Abramov将这些原则解释如下(为了更好地适应场景,我对代码进行了一些修改):

从“React”导入React;
从“react dom”导入react dom;
//减速器。
const news=(state=[],action)=>{
开关(动作类型){
案例“添加新闻项目”:{
返回[…状态,action.newItem];
}
默认值:{
返回状态;
}
}
};
//商店。
常量createStore=(减速机)=>{
让国家;
让侦听器=[];
const subscribe=(侦听器)=&gt{
listeners.push(listener);
返回()=&gt{
侦听器=侦听器.filter(cb=>cb!==侦听器);
};
};
const getState=()=>state;
常量调度=(操作)=&gt{
状态=减速器(状态、动作);
forEach(cb=>cb());
};
调度({});
返回{subscribe,getState,dispatch};
};
//使用reducer初始化存储。
const store=createStore(新闻);
//组成部分。
const News=React.createClass({
onAddNewsItem(){
const{newsttitle}=this.refs;
仓库调度({
键入:“添加新闻项目”,
新闻项:{title:newsttitle.value}
});
},
render(){
const{news}=this.props;
返回(
<div>
<输入ref=“newsttitle”/>
<button onClick={this.onAddNewsItem}>添加</button>
<ul>
{news.map(({title})=><li>{title}</li>)}
</ul>
</div>
);
}
});
//存储分派时将执行的处理程序。
常量呈现=()=>{
ReactDOM.render(
<News News={store.getState()}/>,
document.getElementById('news')
);
};
//入口点。
存储。订阅(呈现);
render();

此外,这些视频还进一步详细演示了如何实现以下方面的不变性:

  • 阵列
  • 物体

发表评论