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

简介:

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

1.15 减少隐式副作用

在JavaScript中有两类十分常见却可以轻易规避的错误。第一类是语法错误,第二类是无意识的隐式副作用。
隐式副作用是代码复用的大敌,因为它导致函数被其作用域外的状态所劫持。隐式副作用的产生是由于多个函数间共享变量或属性所致,举例来说,应用中有一个购物车功能,用户在会话期间可以对购物车的内容进行保存。
用户想要更改当前会话中购物车的内容顺序,只需:

test('Order WITH unintentional side effect.', function () {
      var cartProto = {
          items: [],

          addItem: function addItem(item) {
            this.items.push(item);
          }
        },

        createCart = function (items) {
          var cart = Object.create(cartProto);
          cart.items = items;
          return cart;
        },

        // Load cart with stored items.
        savedCart = createCart(["apple", "pear", "orange"]),

        session = {
          get: function get() {
            return this.cart;
          },

          // Grab the saved cart.
          cart: createCart(savedCart.items)
        };

      // addItem gets triggered by an event handler somewhere:
      session.cart.addItem('grapefruit');

      ok(session.cart.items.indexOf('grapefruit')
        !== -1, 'Passes: Session cart has grapefruit.');

      ok(savedCart.items.indexOf('grapefruit') === -1,
        'Fails: The stored cart is unchanged.');
    });

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

createCart = function (items) {
  var cart = Object.create(cartProto);
  cart.items = items;
  return cart;
},

请留意此处,cart.items是对原型对象上items属性的直接引用,现在对代码做略微修改。
cart.items = Object.create(items);
新的购物车拥有自己的内容副本,不会再对storedCart对象带来直接影响。
若想减少隐式副作用在程序中的出现概率,最好的方法就是在函数内部对它进行规避。所有外部变量传入函数之前,最好是先经过一轮复制,不要将原始值直接传入。
纯函数没有隐式副作用,因为它在调用时不会更改任何外部变量,决定它返回值的因素仅有一个,即它的入参。
尽可能地确保你的函数在执行过程中不会影响外界的状态,在执行结尾处返回修改后的变量副本而不是原始引用,请注意,在整个执行过程中你仍然有更改外部变量的机会。就像REST架构下客户端与服务器的数据传输一样:客户端首先从服务器获取一份数据资源的副本,修改其内容,再将处理过的副本发送回至服务器。建议归建议,大部分情况下开发者为了兼顾到应用的性能不会这么去做,不过使用纯函数或许可以起到一定效果。
在每个函数内部对隐式副作用做规避,一来可以减少代码冗余,二来可以帮助你提升程序分层设计的意识。举例来说,你有一个开工已达数月之久的项目,现在你需要对其新增数据校验功能,当项目中仅有一个函数能够对数据进行提交操作时,你只需把校验功能安插在此函数调用之前即可。但如果这样的函数在项目中有百来个,势必会影响校验功能的加入。
将不同的功能逻辑相互隔离,可以让你更好地管理应用状态。如果函数在执行过程中不会被外界的状态变更所干扰,它只需少量代码就可以完成手头的工作,因为眼前的任务只有一个。
同理,操作DOM的函数一定只专注于DOM树操作,比如视图的render()方法,又如一些DOM树插件。

相关文章
|
2月前
|
JavaScript
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
27 0
|
2月前
|
消息中间件 Web App开发 JavaScript
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
Node.js【简介、安装、运行 Node.js 脚本、事件循环、ES6 作业队列、Buffer(缓冲区)、Stream(流)】(一)-全面详解(学习总结---从入门到深化)
77 0
|
4天前
|
JavaScript 前端开发 测试技术
学习JavaScript
【4月更文挑战第23天】学习JavaScript
11 1
|
12天前
|
JavaScript 前端开发 应用服务中间件
node.js之第一天学习
node.js之第一天学习
|
1月前
|
运维 JavaScript 前端开发
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
发现了一款宝藏学习项目,包含了Web全栈的知识体系,JS、Vue、React知识就靠它了!
|
1月前
|
JavaScript
Vue.js学习详细课程系列--共32节(4 / 6)
Vue.js学习详细课程系列--共32节(4 / 6)
35 0
|
1月前
|
前端开发 搜索推荐 JavaScript
编程笔记 html5&css&js 001 学习编程从网页开始
编程笔记 html5&css&js 001 学习编程从网页开始
|
2月前
|
前端开发 JavaScript
从零开始学习前端开发:HTML、CSS、JavaScript入门指南
【2月更文挑战第1天】本文将带领读者从零开始学习前端开发,介绍HTML、CSS和JavaScript的基础知识与应用,帮助读者快速入门前端开发领域。
65 1
|
2月前
|
数据采集 机器学习/深度学习 JavaScript
画【Python折线图】的一百个学习报告(二、pyecharts引入js文件)
画【Python折线图】的一百个学习报告(二、pyecharts引入js文件)
51 0
|
2月前
|
JSON 前端开发 JavaScript
Webpack【Webpack图片处理、Webpack中proxy代理 、自动清理dist、Webpack优化、JavaScript中的代码检查】(三)-全面详解(学习总结---从入门到深化)
Webpack【Webpack图片处理、Webpack中proxy代理 、自动清理dist、Webpack优化、JavaScript中的代码检查】(三)-全面详解(学习总结---从入门到深化)
35 0
Webpack【Webpack图片处理、Webpack中proxy代理 、自动清理dist、Webpack优化、JavaScript中的代码检查】(三)-全面详解(学习总结---从入门到深化)