eloquentjavascript阅读4 | 青训营笔记

50 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第18天。

我们的机器人将在村子里移动。各个地方都有包裹,每个包裹都是寄到其他地方的。机器人在遇到包裹时就会捡起它们,在到达目的地时就会把它们送到。

机器人必须决定,在每个点上,下一步去哪里。当所有的包裹都被送达时,它就完成了任务。

为了能够模拟这个过程,我们必须定义一个能够描述它的虚拟世界。这个模型告诉我们机器人的位置和包裹的位置。当机器人决定移动到某个地方时,我们需要更新这个模型以反映新的情况。

如果你在思考面向对象的编程,你的第一个冲动可能是开始为世界上的各种元素定义对象:一个机器人的类,一个包裹的类,也许一个地方的类。然后,这些对象可以持有描述其当前状态的属性,例如某个地点的包裹堆,我们可以在更新世界时改变这些属性。

这不对哦,

至少,它通常是这样。听起来像一个对象的事实并不自动意味着它应该是你程序中的一个对象。反射性地为你的应用程序中的每一个概念编写类,往往会给你留下一个相互关联的对象的集合,每个对象都有自己的内部,不断变化的状态。这样的程序往往难以理解,因此容易被破坏。

相反,让我们把村庄的状态压缩到定义它的最小值集合。这里有机器人的当前位置和未交付的包裹集合,每个包裹都有一个当前位置和一个目的地地址。就这样了。

当我们在做这件事的时候,让我们在机器人移动时不改变这个状态,而是为移动后的情况计算一个新的状态。

移动方法是行动发生的地方。它首先检查是否有一条从当前位置到目的地的道路,如果没有,它将返回旧状态,因为这不是一个有效的移动。

然后,它创建一个新的状态,将目的地作为机器人的新位置。但它也需要创建一个新的包裹集–机器人携带的包裹(在机器人的当前位置)需要被移动到新的地方。而那些被送到新地方的包裹需要被送达–也就是说,它们需要从未送达的包裹集中被移除。对地图的调用负责移动,而对过滤器的调用则负责交付。

当包裹对象被移动时,它们并没有被改变,而是被重新创建。移动方法给了我们一个新的村庄状态,但完全保留了旧的状态。

永久数据Object.freeze({value: 5});不管如何改变都不会导致这个属性发生改变。