Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么不变性在JavaScript中如此重要(或需要)?_Javascript_Reactjs_Functional Programming_Immutability_Immutable.js - Fatal编程技术网

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

为什么不变性在JavaScript中如此重要(或需要)?,javascript,reactjs,functional-programming,immutability,immutable.js,Javascript,Reactjs,Functional Programming,Immutability,Immutable.js,我目前正在研究和框架。在中途,当我读到Facebook的Flux和Redux实现时,我遇到了不变性或不稳定性 问题是,为什么不变性如此重要?变异对象有什么错?这不是让事情变得简单吗 给出一个例子,让我们考虑一个简单的新闻阅读器 app,打开屏幕是新闻标题的列表视图。 如果我将对象数组设置为,初始值为,则无法对其进行操作。这就是不变性原则所说的,对吗?(如果我错了,请纠正我。) 但是,如果我有一个必须更新的新新闻对象呢?在通常情况下,我可以将对象添加到数组中。 在这种情况下,我如何实现目标?是否删

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

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

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

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

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

事实上,情况正好相反:可变性使事情变得更加复杂,至少从长远来看是如此。是的,它使您的初始编码更容易,因为您可以在任何地方更改内容,但当您的程序变得更大时,它就会成为一个问题–如果某个值更改了,是什么更改了它

当您使所有内容都不可变时,这意味着数据不能再意外地更改了。你肯定知道,如果你把一个值传递给一个函数,它就不能在那个函数中被改变

简而言之:如果你使用不可变的值,就很容易对你的代码进行推理:每个人都会得到你的数据的唯一*副本,所以它不会破坏代码的其他部分。想象一下,这使在多线程环境中工作变得多么容易

注1:不变性会带来潜在的性能损失,这取决于您所做的工作,但像Immutable.js这样的东西会尽可能地优化性能

注2:在不太可能发生的情况下,您不确定Immutable.js和ES6
const
的含义完全不同

在通常情况下,我可以将对象添加到数组中。在这种情况下,我如何实现目标?删除存储并重新创建它?向数组中添加对象不是一种成本较低的操作吗?PS:如果这个例子不是解释不变性的正确方法,请让我知道什么是正确的实际例子

是的,您的新闻示例非常好,您的推理也完全正确:您不能只修改现有列表,所以您需要创建一个新列表:

var originalItems = Immutable.List.of(1, 2, 3);
var newItems = originalItems.push(4, 5, 6);
问题是,为什么不变性如此重要?变异对象有什么错?这不是让事情变得简单吗

事实上,情况正好相反:可变性使事情变得更加复杂,至少从长远来看是如此。是的,它使您的初始编码更容易,因为您可以在任何地方更改内容,但当您的程序变得更大时,它就会成为一个问题–如果某个值更改了,是什么更改了它

当您使所有内容都不可变时,这意味着数据不能再意外地更改了。你肯定知道,如果你把一个值传递给一个函数,它就不能在那个函数中被改变

简而言之:如果你使用不可变的值,就很容易对你的代码进行推理:每个人都会得到你的数据的唯一*副本,所以它不会破坏代码的其他部分。想象一下,这使在多线程环境中工作变得多么容易

注1:不变性会带来潜在的性能损失,这取决于您所做的工作,但像Immutable.js这样的东西会尽可能地优化性能

注2:在不太可能发生的情况下,您不确定Immutable.js和ES6
const
的含义完全不同

在通常情况下,我可以将对象添加到数组中。在这种情况下,我如何实现目标?删除存储并重新创建它?向数组中添加对象不是一种成本较低的操作吗?PS:如果这个例子不是解释不变性的正确方法,请让我知道什么是正确的实际例子

是的,您的新闻示例非常好,您的推理也完全正确:您不能只修改现有列表,所以您需要创建一个新列表:

var originalItems = Immutable.List.of(1, 2, 3);
var newItems = originalItems.push(4, 5, 6);

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

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

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

可预测性

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

性能

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

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

你可以阅读更多关于这方面的内容

突变跟踪

除了减少内存使用外,不变性还允许您通过使用引用和值相等来优化应用程序。这使我们很容易看到是否有任何变化。例如,react组件中的状态更改。您可以使用
shouldComponentU
new state  = r(current state, action)
// this function will change the letter in all the array
function fillWithZ(arr) {
    for (var i = 0; i < arr.length; ++i) {
        if (i === 4) // rare condition
            return arr; // some error here

        arr[i] = "Z";
    }

    return arr;
}

console.log(fillWithZ(["A","A","A"])) // ok, valid state
console.log(fillWithZ(["A","A","A","A","A","A"])) // bad, invalid state
class Foo {

      baz() {
          // .... 
      }

      bar() {
          // ....
      }

}

const f = new Foo();
f.baz();
f.bar(); // this is ok

f.bar();
f.baz(); // this blows up
const car = { brand: 'Ferrari' };
doSomething(car);
console.log(car); // { brand: 'Fiat' }
const userMessage  = { 
   user: "userId",
   topic: "topicId"
   content: {}
}

validateMessage(userMessage)
saveMessage(userMessage) 
sendMessageViaEmail(userMessage)
**sendMessageViaMobilePush(userMessage)** 

console.log(userMessage) // => ?