天天看点

《JavaScript应用程序设计》一一1.15 减少隐式副作用

本节书摘来华章计算机出版社《javascript应用程序设计》一书中的第1章,第1.15 节,作者:eric elliott 更多章节内容可以访问云栖社区“异步社区”公众号查看。

在javascript中有两类十分常见却可以轻易规避的错误。第一类是语法错误,第二类是无意识的隐式副作用。

隐式副作用是代码复用的大敌,因为它导致函数被其作用域外的状态所劫持。隐式副作用的产生是由于多个函数间共享变量或属性所致,举例来说,应用中有一个购物车功能,用户在会话期间可以对购物车的内容进行保存。

用户想要更改当前会话中购物车的内容顺序,只需:

很不幸,当用户在当前会话中添加或删除购物车内容时,之后的购物车设置信息也被连带删除了,导致这个问题的代码片段是:

请留意此处,cart.items是对原型对象上items属性的直接引用,现在对代码做略微修改。

cart.items = object.create(items);

新的购物车拥有自己的内容副本,不会再对storedcart对象带来直接影响。

若想减少隐式副作用在程序中的出现概率,最好的方法就是在函数内部对它进行规避。所有外部变量传入函数之前,最好是先经过一轮复制,不要将原始值直接传入。

纯函数没有隐式副作用,因为它在调用时不会更改任何外部变量,决定它返回值的因素仅有一个,即它的入参。

尽可能地确保你的函数在执行过程中不会影响外界的状态,在执行结尾处返回修改后的变量副本而不是原始引用,请注意,在整个执行过程中你仍然有更改外部变量的机会。就像rest架构下客户端与服务器的数据传输一样:客户端首先从服务器获取一份数据资源的副本,修改其内容,再将处理过的副本发送回至服务器。建议归建议,大部分情况下开发者为了兼顾到应用的性能不会这么去做,不过使用纯函数或许可以起到一定效果。

在每个函数内部对隐式副作用做规避,一来可以减少代码冗余,二来可以帮助你提升程序分层设计的意识。举例来说,你有一个开工已达数月之久的项目,现在你需要对其新增数据校验功能,当项目中仅有一个函数能够对数据进行提交操作时,你只需把校验功能安插在此函数调用之前即可。但如果这样的函数在项目中有百来个,势必会影响校验功能的加入。

将不同的功能逻辑相互隔离,可以让你更好地管理应用状态。如果函数在执行过程中不会被外界的状态变更所干扰,它只需少量代码就可以完成手头的工作,因为眼前的任务只有一个。

同理,操作dom的函数一定只专注于dom树操作,比如视图的render()方法,又如一些dom树插件。

继续阅读