理解javascript模块化


Posted in Javascript onMarch 28, 2016

模块化是一个通用的编程最佳实践。程序的模块化使我们可以更方便地使用别人的代码,想要什么功能,就加载什么模块,从而提高代码的利用效率,增加开发速度。

模块就像积木,有了它,我们可以搭出各种各种功能样式的程序。积木有什么特点?小而简单。同样的,我们程序中的模块也要做到这一点,确保自己创建的函数一次只完成一个工作,这样其他开发者可以简单地调试与修改你的代码,而不需浏览所有代码才能弄清每一个代码块执行了什么功能。只有做到像这样地小而简单,才能实现其通用功能。

一、javascript模块化的方法
1、函数封装
JavaScript的作用域就是基于函数的,所以我们可以把函数作为模块。

function fn1(){
  //code
}

function fn2(){
  //code
}

缺点:"污染"了全局变量,无法保证不与其他模块发生变量名冲突

2、对象

var myModule1 = {
  fn1: function(){
    //code
  },
  fn2: function(){
    //code
  }
}

缺点:会暴露所有模块成员,内部状态可以被外部改写

立即自执行函数——推荐

var myModule = (function(){
  function fn1(){
    //code
  },
  function fn2(){
    //code
  },
  return {
    fn1: fn1,
    fn2: fn2
  };
})();

二、小而简单
关于小而简单,我们看一个例子,比如我们现在想编写一个创建新链接的函数,并且为类型是"mailto"超链接添加一个class。可以这样做:

function addLink(text, url, parentElement) {
  var newLink = document.createElement('a');//创建a标签
  newLink.setAttribute('href', url);//为a标签设置href属性
  newLink.appendChild(document.createTextNode(text));//为a标签添加文本
  if(url.indexOf("mailto:")==-1){
    newLink.className = 'mail';
  }
  parentElement.appendChild(newLink);//将a标签添加到页面
}

这样写能够工作,但你或许会发现自己又不得进行其他的功能添加,于是,这个函数又不适用了。所以,函数越特殊,越难以适用于不同情形。
这里的函数写法没有达到模块化的要求——一个函数只干一件事。我们将函数改编下:

function createLink(text,url) {
  var newLink = document.createElement('a');
  newLink.setAttribute('href', url);
  newLink.appendChild(document.createTextNode(text));
  return newLink;
}

这里createLink函数只做一件事——创建并返回要添加到页面中的a标签(小而简单),这样我们就可以在任何需要创建超链接的情况下调用这样函数。

三、CommonJS
在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块与操作系统和其他应用程序互动,否则根本没法编程。虽然JavaScript在web端发展这么多年,但是第一个流行的模块化规范却由服务器端的JavaScript应用带来,CommonJS规范是由NodeJS发扬光大,这标志着JavaScript模块化编程正式登上舞台。
node.js的模块系统,就是依据CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。
加载模块:

var math = require('math');
调用模块:

  math.add(2,3)
CommonJS规范不适用于浏览器环境,因为它存在一个重大的局限,上例中第二行math.add(2, 3)必须要在math.js加载完成后才能运行,而模块都放在服务器端,所以可能要等很长时间,等待时间取决于网速的快慢。

CommonJS规范适用于服务器端,因为对于服务端来说,所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间

四、模块应该怎么定义和怎么加载?
AMD
Asynchronous Module Definition异步模块定义,主要代表:require.js
目的:
(1)实现js文件的异步加载,避免网页失去响应;
(2)管理模块之间的依赖性,便于代码的编写和维护。

1、定义模块

define(["./cart", "./inventory"], function(cart, inventory) {
  //通过[]引入依赖
  return {
    color: "blue",
    size: "large",
    addToCart: function() {
      inventory.decrement(this);
      cart.add(this);
    }
  }
}
);

2、加载模块

require( ["some/module", "my/module", "a.js", "b.js"],
function(someModule,  myModule) {
  //This function will be called when all the dependencies
  //listed above are loaded. Note that this function could
  //be called before the page is loaded.
  //This callback is optional.
}
 );

CMD
Common Module Definition通用模块定义,CMD规范是国内发展出来的。主要代表:sea.js

1、定义模块

define(function(require, exports, module) {
 // 通过 require 引入依赖
 var $ = require('jquery');
 var Spinning = require('./spinning');
 // 通过 exports 对外提供接口
 exports.doSomething = ...
 // 或者通过 module.exports 提供整个接口
 module.exports = ...
});

2、加载模块

seajs.use("../static/hello/src/main")
区别:

对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.

CMD 推崇依赖就近,AMD 推崇依赖前置。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
jQuery maxlength文本字数限制插件
Apr 16 Javascript
EasyUi tabs的高度与宽度根据IE窗口的变化自适应代码
Oct 26 Javascript
JavaScript 类型的包装对象(Typed Wrappers)
Oct 27 Javascript
用html+css+js实现的一个简单的图片切换特效
May 28 Javascript
JS在可编辑的div中的光标位置插入内容的方法
Nov 20 Javascript
jQuery中wrapInner()方法用法实例
Jan 16 Javascript
jQuery+AJAX实现无刷新下拉加载更多
Jul 03 Javascript
jquery实现select下拉框美化特效代码分享
Aug 18 Javascript
浅谈Node.js:fs文件系统模块
Dec 08 Javascript
js实现固定宽高滑动轮播图效果
Jan 13 Javascript
简述vue-cli中chainWebpack的使用方法
Jul 30 Javascript
node.JS二进制操作模块buffer对象使用方法详解
Feb 06 Javascript
谈一谈jQuery核心架构设计
Mar 28 #Javascript
javascript函数自动执行常用方法汇总
Mar 28 #Javascript
JavaScript利用HTML DOM进行文档操作的方法
Mar 28 #Javascript
JavaScript常用本地对象小结
Mar 28 #Javascript
Bootstrap 粘页脚效果
Mar 28 #Javascript
jQuery实现的多滑动门,多选项卡效果代码
Mar 28 #Javascript
轻量级jQuery插件slideBox实现带底栏轮播(焦点图)代码
Mar 28 #Javascript
You might like
php 获取一个月第一天与最后一天的代码
2010/05/16 PHP
php的大小写敏感问题整理
2011/12/29 PHP
PHP中IP地址与整型数字互相转换详解
2014/08/20 PHP
CI框架中类的自动加载问题分析
2016/11/21 PHP
PHP命名空间定义与用法实例分析
2019/08/14 PHP
jQuery Validation实例代码 让验证变得如此容易
2010/10/18 Javascript
两个Javascript小tip资料
2010/11/23 Javascript
通过javascript获取iframe里的值示例代码
2013/06/24 Javascript
利用js判断浏览器类型(是否为IE,Firefox,Opera浏览器)
2013/11/22 Javascript
引用其它js时如何同时处理多个window.onload事件
2014/09/02 Javascript
nodejs中实现sleep功能实例
2015/03/24 NodeJs
JS实现带圆弧背景渐变效果的导航菜单代码
2015/10/13 Javascript
JS更改select内option属性的方法
2015/10/14 Javascript
全面解析Angular中$Apply()及$Digest()的区别
2016/08/04 Javascript
JavaScript实现DOM对象选择器
2016/09/24 Javascript
ionic中列表项增加和删除的实现方法
2017/01/22 Javascript
深入理解requireJS-实现一个简单的模块加载器
2018/01/15 Javascript
layui 对弹窗 form表单赋值的实现方法
2019/09/04 Javascript
Vue中点击active并第一个默认选中功能的实现
2020/02/24 Javascript
js实现无缝轮播图效果
2020/03/09 Javascript
解决vue与node模版引擎的渲染标记{{}}(双花括号)冲突问题
2020/09/11 Javascript
javascript全局自定义鼠标右键菜单
2020/12/08 Javascript
使用python生成目录树
2018/03/29 Python
Django 配置多站点多域名的实现步骤
2019/05/17 Python
PyQt编程之如何在屏幕中央显示窗体的实例
2019/06/18 Python
用Python+OpenCV对比图像质量的几种方法
2019/07/15 Python
使用python模拟命令行终端的示例
2019/08/13 Python
python使用Word2Vec进行情感分析解析
2020/07/31 Python
HTML5适合的情人节礼物有纪念日期功能
2021/01/25 HTML / CSS
英国国家美术馆商店:National Gallery
2019/05/01 全球购物
新西兰最大、占有率最高的综合性药房:PharmacyDirect药房中文网
2020/11/03 全球购物
下面这个程序执行后会有什么错误或者效果
2014/11/03 面试题
UNIX命令速查表
2012/03/10 面试题
社区志愿服务活动感想
2015/08/07 职场文书
公司晚会主持词
2019/04/17 职场文书
python微信智能AI机器人实现多种支付方式
2022/04/12 Python