前端跟我学Web前端之路让前端飞

使用合适的设计模式一步步优化前端代码

2017-10-27  本文已影响46人  iKcamp

作者:晓飞
本文原创,转载请注明作者及出处


在后端语言中,设计模式应用的较为广泛。如Spring中常见的工厂模式、装饰者模式、单例模式、迭代器模式。但是在日常的前端开发中,设计模式使用的较少,或者大家的代码已经遵循了某某设计模式但是我们并不知道。常见的设计模式有23种,如果单纯的按照模式名称+名词解释的方式来写这篇文章,可能太枯燥了或者很难理解记忆,所以我打算换一种方式。下面我们以一个例子开始我们今天的文章。

假设我们有一个这样的需求:
let page = {
  init: ()=>{
    //此处(placeA)有很多业务代码或者调用了很多page中的其他初始化函数
  },
  ....
};

现在业务迭代,需要我们在page.init()初始化代码块的最后增加一些功能,同时不影响原先的功能。按照正常的写法,我们可能会像下面这样写:

let page = {
  init: ()=>{
    //placeA
    page.newFunction();
  },
  newFunction: ()=>{
    ...
  }
};

这样写是可以解决我们的需求,但是这样的代码是具有侵略性的,我们不得不在原先的代码的合适位置新增我们需要的代码。但我们思考一个问题,如果我们用了某个插件或者某个被ungly、minify之后的代码呢,我们怎么在找到合适的位置添加我们需要的功能呢?大家可以先自己思考一下,再看下面的内容。

首先我们先看解决方案,再思考其背后的东西。
//我们可以在Function的原型链上定义一个扩展函数,以实现我们的需求。
Function.prototype.fnAfter = function(fn) {
  var _self = this;
  return function() {
    _self.apply(this, arguments);
    fn.apply(this, arguments);
  }
};

page.init  = (page.init || function() {}).fnAfter(function() {
  console.log('我们要追加的功能成功啦~');
});

page.init();

上面的代码已经能够实现我们的需要了,但是其实还是不够好或者可以写的更灵活一些。因为我希望可以可以做到像jquery的链式调用那样,可以一直往后面追加新的功能。那么我们在上面代码的基础上再扩展下,其实很简单,我们只要再Function.prototype.fnAfter中再返回自身就好了。

Function.prototype.fnAfter = function(fn) {
  var _self = this;
  return function() {
    var fnOrigin = _self.apply(this, arguments);
    fn.apply(this, arguments);
    return fnOrigin;
  }
};

其实上面的代码写法还是可以优化的。比如:

//每次扩展的时候我们都需要这么写
page.init  = (page.init || function() {}).fnAfter(function() {
  //...
});
//我们能不能再优化下,比如容错代码 || function(){} 在一个地方统一处理  
//或者我们新建一个工厂函数来帮我们统一做这样的事情,这里我们就不展开了,文章篇幅有限。
我们上面的扩展其实就是遵循的是面向对象程序设计中的开放-封闭原则(OCP)。官方对OCP的解释是:软件实体(类、模块、函数...)应该是可以扩展的,但是不可修改。设计模式中有很多模式都遵循了开发-封闭原则,比如:发布-订阅者模式、模板方法模式、策略模式、代理模式。

有的时候我们通过扩展来提高代码的灵活性并不能解决所有的场景需要,在不可避免发生修改的时候,我们可以通过增加配置文件,让用户修改配置文件以实现个性化需求也是合理的。修改配置远比修改源代码要简单的多。

有了上面的引入,我们来看几个前端开发中常见的设计模式。
看了上面的文章,相信大家对设计模式的好处有了直观的了解,也大致掌握了单例模式及观察者模式。

设计模式都是经过了大量的代码、软件实践而总结出来的优秀的组织实践方案。每种设计模式都有它的适应场景,有的场景也会使用多种设计模式。只有了解了更多的设计模式,掌握各个设计模式自己的适应场景,才能更好的为我们所用。

但是过早的优化不一定是好事或者不是必须的,有时候我们可以一开始并不去优化,等到某个应用场景下出现了代码组织混乱、需要额外扩展等问题,我们再优化重构,以防过早优化导致的不必要性或者只是增加了代码不必要的复杂性。就像redux,如果一个页面组件与组件之间有数据共享、需要在任意组件内部拿到某个数据、任意一个组件中某个行为导致的数据变化需要通知到所有用到的地方,那么这个时候可以使用redux,一些简单的表单页面或者展示页完全可以不用redux。

看到这里不容易,最后给大家讲一个笑话轻松一下:
从前有只麋鹿,它在森林里玩儿,不小心走丢了。  
于是它给它的好朋友长颈鹿打电话:“喂…我迷路辣。”  
长颈鹿听见了回答说:“喂~我长颈鹿辣~”

参考:曾探《javascript设计模式与开发实践》


iKcamp官网:http://www.ikcamp.com

访问官网更快阅读全部免费分享课程:《iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享》。
包含:文章、视频、源代码

iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。

iKcamp最新活动

报名地址:http://www.huodongxing.com/event/5409924174200

“天天练口语”小程序总榜排名第四、教育类排名第一的研发团队,面对面沟通交流。

上一篇下一篇

猜你喜欢

热点阅读