为什么JavaScript中的不变性如此重要(或需要)? [英] Why is immutability so important (or needed) in JavaScript?

查看:153
本文介绍了为什么JavaScript中的不变性如此重要(或需要)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在 React JS React Native 框架。在我读到的时候,我遇到了Immutability或者 Immutable-JS库。 Facebook的Flux和Redux实现。



问题是,为什么不变性如此重要?变异对象有什么问题?它不是简单吗?



举一个例子,让我们考虑一个简单的新闻阅读器应用程序,其中开幕式为列表视图的新闻标题。



如果我设置对象数组的值为最初,我无法操作它。这就是不变性原理所说的,对吗? (纠正我,如果我错了。)
但是,如果我有一个新的新闻对象,必须更新?在通常情况下,我可以将该对象添加到数组中。
在这种情况下我如何实现?删除商店并重新创建它?
是不是将一个对象添加到数组中一个更便宜的操作?



PS:如果示例不是解释不变性的正确方法,请让我知道什么是正确的实际例子。

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


问题是,为什么不变性如此重要?
变异对象有什么错误?它不是简单吗?



基本上,这归结于不变性提高了可预测性,性能(间接),并允许突变跟踪。

可预测性

突变隐藏改变,副作用,这可能会导致讨厌的错误。当您执行不变性时,您可以保持应用程序架构和智能模型的简单性,这使得您可以更轻松地推理应用程序。 p>

即使将值添加到不可变对象中,也意味着需要在需要复制现有值的情况下创建新实例,并且需要将新值添加到新对象中,内存,不可变对象可以利用结构共享来减少内存开销。
$ b


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


你可以阅读更多关于 here



突变跟踪 p 除了减少内存使用量之外,不变性允许您通过引用和值相等来优化应用程序。这使得很容易看到是否有任何改变。例如,反应组件中的状态改变。您可以使用 shouldComponentUpdate 通过比较状态对象来检查状态是否相同,并防止不必要的渲染。
您可以在这里阅读更多关于此



其他资源:




如果我最初设置了一个带有值的对象数组。我不能
操纵它。这就是不变性原理所说的,对吗?(如果我错了,请纠正
)。但是,如果我有一个新的News对象必须更新
呢?在通常情况下,我可以将该对象添加到
数组中。我在这种情况下如何实现?删除商店&重新创建它?
是不是将一个对象添加到数组中一个更便宜的操作?

是的,这是正确的。如果您对如何在您的应用程序中实现这一点感到困惑,我会建议您查看 redux 的工作方式这对熟悉核心概念很有帮助。



我喜欢用Redux作为例子,因为它包含了不变性。它有一个单一的不可变状态树(称为 store ),其中所有的状态变化都是通过调度由接受前一个状态的reducer处理的动作以及所述动作(一次一个)并返回应用程序的下一个状态。您可以阅读更多关于此处的核心原则。



egghead.io 上有一个很好的复习课程,其中



  import从'react'反应; 
从'react-dom'导入ReactDOM;

//减速器。
const news =(state = [],action)=> {
switch(action.type){
case'ADD_NEWS_ITEM':{
return [... state,action.newsItem];
}
默认值:{
return state;
}
}
};

//商店。
const createStore =(reducer)=> {
让州;
let listeners = [];

const subscribe =(listener)=> {
listeners.push(listener);

return()=> {
listeners = listeners.filter(cb => cb!== listener);
};
};

const getState =()=>州;

const dispatch =(action)=> {
state = reducer(state,action);
listeners.forEach(cb => cb());
};

dispatch({});

return {subscribe,getState,dispatch};
};

//使用reducer初始化存储。
const store = createStore(news);

//组件。
const News = React.createClass({
onAddNewsItem(){
const {newsTitle} = this.refs;

store.dispatch({
键入:'ADD_NEWS_ITEM',
newsItem:{title:newsTitle.value}
});
},

render(){
const { news} = this.props;

return(
< div>
< input ref =newsTitle/>
< button onClick = { this.onAddNewsItem}>添加< / gt;
< ul>
{news.map(({title})=>< li> {title}< / li>)}
< / ul>
< / div>
);
}
});

//商店派送时将执行的处理程序。
const render =()=> {
ReactDOM.render(
< News news = {store.getState()} /> ;,
document.getElementById('news')
);
};

//入口点。
store.subscribe(render);
render();

此外,这些视频还详细介绍了如何实现以下方面的不变性:




I am currently working on React JS and React Native frameworks. On the half way road I came across Immutability or the Immutable-JS library, when I was reading about Facebook's Flux and Redux implementation.

The question is, why is immutability so important? What is wrong in mutating objects? Doesn't it make things simple?

Giving an example, let us consider a simple News reader app with the opening screen being a list view of news headlines.

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 and recreate it? Isn't adding an object to the array a less expensive operation?

PS: If the example is not the right way to explain immutability, please do let me know what's the right practical example.

解决方案

I have recently been researching the same topic. I'll do my best to answer your question(s) and try to share what I have learned so far.

The question is, why is immutability so important? What is wrong in mutating objects? Doesn't it make things simple?

Basically it comes down to the fact that immutability increases predictability, performance (indirectly) and allows for mutation tracking.

Predictability

Mutation hides change, which create (unexpected) side effects, which can cause nasty bugs. When you enforce immutability you can keep your application architecture and mental model simple, which makes it easier to reason about your application.

Performance

Even though adding values to an immutable Object means that a new instance needs to be created where existing values need to be copied and new values need to be added to the new Object which cost memory, immutable Objects can make use of structural sharing to reduce memory overhead.

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.

You can read more about this here.

Mutation Tracking

Besides reduced memory usage, immutability allows you to optimize your application by making use of reference- and value equality. This makes it really easy to see if anything has changed. For example a state change in a react component. You can use shouldComponentUpdate to check if the state is identical by comparing state Objects and prevent unnecessary rendering. You can read more about this here.

Additional resources:

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?

Yes this is correct. If you're confused on how to implement this in your application I would recommend you to look at how redux does this to get familiar with the core concepts, it helped me a lot.

I like to use Redux as an example because it embraces immutability. It has a single immutable state tree (referred to as store) where all state changes are explicit by dispatching actions which are processed by a reducer that accepts the previous state together with said actions (one at a time) and returns the next state of your application. You can read more about it's core principles here.

There is an excellent redux course on egghead.io where Dan Abramov, the author of redux, explains these principles as follows (I modified the code a bit to better fit the scenario):

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();

Also, these videos demonstrate in further detail how to achieve immutability for:

这篇关于为什么JavaScript中的不变性如此重要(或需要)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆