模块化开发在编程开发中是一个非常重要的概念,一个优秀的模块化项目的后期维护成本可以大大降低。本文主要介绍了JavaScript模块化开发的那些事,文中通过一个小故事比较直观地阐述了模块化开发的过程。

小A是某个创业团队的前端工程师,负责编写项目的Javascript程序。

全局变量冲突

根据自己的经验,小A先把一些常用的功能抽出来,写成函数放到一个公用文件base.js中:

var _ = {

$: function(id) { return document.getElementById(id); },

getCookie: function(key) { ... },

setCookie: function(key, value) { ... }

};

小A把这些函数都放在_对象内,以防过多的全局变量造成冲突。他告诉团队的其他成员,如果谁想使用这些函数,只要引入base.js就可以了。

小C是小A的同事,他向小A反映:自己的页面引入了一个叫做underscore.js的类库,而且,这个类库也会占用_这个全局变量,这样一来就会跟base.js中的_冲突了。小A心想,underscore.js是第三方类库,估计不好改,但是base.js已经在很多页面铺开,不可能改。最后小A只好无奈地把underscore.js占用的全局变量改了。

此时,小A发现,把函数都放在一个名字空间内,可以减少全局变量冲突的概率,却没有解决全局变量冲突这个问题。

依赖

随着业务的发展,小A又编写了一系列的函数库和UI组件,比方说标签切换组件tabs.js,此组件需调用base.js以及util.js中的函数。

有一天,新同事小D跟小A反映,自己已经在页面中引用了tabs.js,功能却不正常。小A一看就发现问题了,原来小D不知道tabs.js依赖于base.js以及util.js,他并没有添加这两个文件的引用。于是,他马上进行修改:

<script src="tabs.js"></script>

<script src="base.js"></script>

<script src="util.js"></script>

然而,功能还是不正常,此时小A教训小D说:“都说是依赖,那被依赖方肯定要放在依赖方之前啊”。原来小D把base.js和util.js放到tabs.js之后了。

小A心想,他是作者,自然知道组件的依赖情况,但是别人就难说了,特别是新人。

过了一段时间,小A给标签切换组件增加了功能,为了实现这个功能,tabs.js还需要调用ui.js中的函数。这时,小A发现了一个严重的问题,他需要在所有调用了tabs.js的页面上增加ui.js的引用!!!

又过了一段时间,小A优化了tabs.js,这个组件已经不再依赖于util.js,所以他在所有用到tabs.js的页面中移除了util.js的引用,以提高性能。他这一修改,出大事了,测试组MM告诉他,有些页面不正常了。小A一看,恍然大悟,原来某些页面的其他功能用到了util.js中的函数,他把这个文件的引用去掉导致出错了。为了保证功能正常,他又把代码恢复了。

小A又想,有没有办法在修改依赖的同时不用逐一修改页面,也不影响其他功能呢?

模块化

小A逛互联网的时候,无意中发现了一种新奇的模块化编码方式,可以把它之前遇到的问题全部解决。

在模块化编程方式下,每个文件都是一个模块。每个模块都由一个名为define的函数创建。例如,把base.js改造成一个模块后,代码会变成这样:

define(function(require, exports, module) {

exports.$ = function(id) { return document.getElementById(id); };

exports.getCookie = function(key) { ... };

exports.setCookie = function(key, value) { ... };

});

base.js向外提供的接口都被添加到exports这个对象。而exports是一个局部变量,整个模块的代码都没有占用半个全局变量。

那如何调用某个模块提供的接口呢?以tabs.js为例,它要依赖于base.js和util.js:

define(function(require, exports, module) {

var _ = require('base.js'), util = require('util.js');

var div_tabs = _.$('tabs');

// .... 其他代码

});

一个模块可以通过局部函数require获取其他模块的接口。此时,变量_和util都是局部变量,并且,变量名完全是受开发者控制的,如果你不喜欢_,那也可以用base:

define(function(require, exports, module) {

var base = require('base.js'), util = require('util.js');

var div_tabs = base.$('tabs');

// .... 其他代码

});

一旦要移除util.js、添加ui.js,那只要修改tabs.js就可以了:

define(function(require, exports, module) {

var base = require('base.js'), ui = require('ui.js');

var div_tabs = base.$('tabs');

// .... 其他代码

});

加载器

由于缺乏浏览器的原生支持,如果我们要用模块化的方式编码,就必须借助于一个叫做加载器(loader)的东西。

目前加载器的实现有很多,比如require.js、seajs。而JRaiser类库也有自己的加载器。

JavaScript模块化开发的那些事的更多相关文章

  1. Javascript模块化开发,使用模块化脚本加载工具RequireJS,提高你代码的速度和质量。

    随着前端JavaScript代码越来越重,如何组织JavaScript代码变得非常重要,好的组织方式,可以让别人和自己很好的理解代码,也便于维护和测试.模块化是一种非常好的代码组织方式,本文试着对Ja ...

  2. Javascript 模块化开发上线解决方案

    最近又换部门了,好频繁地说...于是把这段时间搞的小工具们简单整理了一下,作了一个小的总结.这次用一个简单业务demo来向大家介绍一下Javascript模块化开发的方式和自动化合并压缩的一些自己的处 ...

  3. JavaScript模块化开发整理

    在网上已经有很多关于模块化开发的文章了,这里还是按照自己的理解来整理一下. 随着项目文件的越来越大和需求的越来越贴近现实(我发现现在客户不如:一个领导说我要审批你们报上来的资料,系统发布以后用的还不错 ...

  4. Javascript模块化开发-轻巧自制

    Javascript模块化开发-轻巧自制 一.前言现在javascript的流行,前端的代码越来越复杂,所以我们需要软件工程的思想来开发前端.模块化是必不可少的,这样不仅能够提高代码的可维护性.可扩展 ...

  5. 详解JavaScript模块化开发

    什么是模块化开发? 前端开发中,起初只要在script标签中嵌入几十上百行代码就能实现一些基本的交互效果,后来js得到重视,应用也广泛起来了,jQuery,Ajax,Node.Js,MVC,MVVM等 ...

  6. 2.精通前端系列技术之JavaScript模块化开发 seajs(一)

    在使用seajs模块化开发之前,直接在页面引用js会容易出现冲突及依赖相关的问题,具体问题如下 问题1:多人开发脚本的时候容易产生冲突(比如全局参数冲突,方法名冲突),可以使用命名空间降低冲突,不能完 ...

  7. JavaScript模块化开发实例

    最近接触了一些JavaScript开发的例子,在这里与大家一起分享一下: 例子:当我们一个团队在写Js文件的时候,你一个人写的JS代码自己可以看懂也可以维护,但是别人想对你的JS进行扩展的话,如果都在 ...

  8. JavaScript模块化开发&&模块规范

    在做项目的过程中通常会有一些可复用的通用性功能,之前的做法是把这个功能抽取出来独立为一个函数统一放到commonFunctions.js里面(捂脸),实现类似于snippets的代码片段收集. fun ...

  9. (转)详解JavaScript模块化开发

    https://segmentfault.com/a/1190000000733959 什么是模块化开发? 前端开发中,起初只要在script标签中嵌入几十上百行代码就能实现一些基本的交互效果,后来j ...

随机推荐

  1. vue-cli目录结构及说明

    使用vue-cli有时会出现一些莫名的问题,清楚项目的结构文件及其意义方便更好的开发和解决问题,介绍如下: build/ // 项目构建(webpack)相关代码 build.js // 生产环境构建 ...

  2. 51nod 1405【DFS】

    思路: 对于结点 u 的子节点 v, 如果已经一直到结点 u 的答案ans[u],那么转移到对于结点 v,num[v] 为 v为根的树的结点个数,那么对于结点v的答案相对于结点u的答案来说, ans[ ...

  3. PAT 1043【BST与二叉树】

    考察: 1.二叉树的建树 2.前序遍历,后序遍历 3.BST的特性 这题的思路: 告诉你数组是先序遍历的,so 根已经知道了(数组首位元素),那么按照BST,建一下树(要两次,另外一次是镜像的): 跑 ...

  4. Zookeeper下载方法

    Zookeeper官网地址:http://zookeeper.apache.org/             Zookeeper下载链接:http://mirrors.tuna.tsinghua.ed ...

  5. docker下载安装教程(Linux系统)

    原文链接:http://www.studyshare.cn/blog-front//software/details/1160/0一.检查 1.检查安装的docker 命令:yum list inst ...

  6. input和button不同高 和 rem

    rem的使用 浏览器中默认的字体大小是 16px,此时为 100%.当我们在使用 rem 的时候,常常给 html设置为 html{font-size:62.5;},这样的好处是 1rem 刚好为 1 ...

  7. POJ 3537 Crosses and Crosses(sg博弈)

    题目:在1*n 的棋盘里面,A和B都在里面画叉 , 如果谁可以画了一个叉后,可以连成3个叉,那谁胜利 : 分析: 首先考虑如果我在玩游戏,我最希望对手可以画出-x-x or  -xx-   ,  这种 ...

  8. jvm 锁Lock

    自旋锁 线程想要获得一个对象的锁,如果没有得到,会继承占用CPU尝试获取锁, 线程不进入阻塞状态,仍然在Running 锁消除 public void lockTest() { String aa = ...

  9. SVN服务器地址更换方法

    由于工作需要,已将SVN服务器从172.16.8.xxx上迁移至172.16.8.yyy上,SVN地址变为:https://172.16.8.yyy:8443/svn,原下载到客户端电脑的svn不需要 ...

  10. ubuntu apache2配置多站点

    ubuntu下使用sudo apt-get install apache2方法安装时,配置文件主要在/etc/apache2/目录下.主要有: apache2.conf : 主配置文件,会通过incl ...