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

标签 javascript reactjs functional-programming immutability immutable.js

我目前正在处理React JSReact 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/

相关文章:

javascript - 将此 js 代码从内联更改为外部

javascript - 带有velocity.js的阶跃函数?

javascript - 语义 UI 下拉菜单 : prevent onchange event from firing when selected option is changed programmatically

javascript - 过滤 Javascript 数组并仅返回具有填充键的对象

javascript - 我正在用 HTML 编写类似 PDF 的页面格式。超出页面高度时如何将文本移动到下一页

programming-languages - 函数式编程和强类型之间有联系吗?

javascript - NavLink 组件不允许网站渲染并显示其中所有元素的奇怪错误

reactjs - 使用 Jest 和 react 测试库进行单元测试自定义 Hook

java - java中Akka流按id排序

scala - 函数式根据 Scala 中的值创建列表