JavaScript 模块化
当项目越来越大时,会遇到一些问题:
1.命名冲突
2.文件依赖
所有就有了javascript模块化开发概念。
模块化开发的演变:
1.函数块:最开始用全局函数将代码块包括在函数体内,然后把很多函数写在一个js文件,然后引入js文件,这种方式会导致:全局变量污染和命令冲突,模块之间的关系也不明确。
2.命名空间:把函数和变量封装在对象里,可以较好的避免命名冲突问题。但是这方式会导致:多层级嵌套(命名空间越来越长),暴露了所有的模块成员,内部状态可以被外部改写,不安全。
3.私有共有成员分离:将函数包裹在立即执行函数(达到函数外部无法访问内部变量的效果)里,以返回的方式选择性对外暴露内部成员。在立即执行函数里形成了一个私有作用域,私有空间的变量和函数不会影响到全局作用域。从某种意义上来说,解决了变量命名冲突的问题。
var calculator = (function () {
// 这里形成一个单独的私有的空间
// 私有成员的作用:
// 1、将一个成员私有化
// 2、抽象公共方法(其他成员中会用到的)
// 私有的转换逻辑
function convert(input){
return parseInt(input);
}
function add(a, b) {
return convert(a) + convert(b);
}
function subtract(a, b) {}
function multiply(a, b) {}
function divide(a, b) {}
return {
add : add,
subtract : subtract,
multiply : multiply,
divide : divide
}
})();
4.模块的拓展与维护
// 计算模块
(function (calculator) {
function convert(input) {
return parseInt(input);
}
calculator.add = function(a, b) {
return convert(a) + convert(b);
}
window.calculator = calculator;
})(window.calculator || {}); // 新增需求
(function (calculator) {
calculator.remain = function (a , b) {
return a % b;
}
window.calculator = calculator;
})(window.calculator || {}); alert(calculator.remain(4,3));
这种方式有利于对庞大的模块的子模块划分。
5.第三方依赖的管理
(function (calculator , $) {
// 依赖函数的参数,是属于模块内部
// console.log($);
calculator.remain = function (a , b) {
return a % b;
}
window.calculator = calculator;
})(window.calculator || {} , jQuery);
传入依赖模块jQuery, 立即执行函数空间里就可以使用第三方依赖了。
创建模块的原则:高内聚低耦合,模块内相关性高,模块间关联低。单一职责
模块使用场景:
1.业务复杂
2.重复逻辑多
3.可拓展性要求高
最后演变到模块化规范:
服务端主要有CommonJS(Node.js 就是基于CommonJS规范实现的模块化 ,webpack也实现了对CommonJS原生支持)
CommonJS的核心思想就是通过 require 方法来同步加载所要依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口,这个规范里,每个文件就是一个模块
其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。例如
// a.js
var x = 5;
var addX = function (value) {
return value + x;
};
module.exports.x = x;
module.exports.addX = addX; 这里的module代表了这个模块,module的exports属性就是对外暴露提供的接口,可以对外导出外部可以访问的变量,如x, addX
这样就可以在其他模块中引入这个模块了
var example = require('./a.js');
console.log(example.x); // 5
CommonJS规范是同步加载模块的,在服务器端,文件都是保存在硬盘上,所以同步加载没有问题,但是对于浏览器端,需要将文件从服务器端请求过来,那么同步加载就不适用了,所以,CommonJS是不适用于浏览器端的。
客户端主要有:AMD( 实现有RequireJS ) / CMD(实现有SeaJS),随着ES6模块化规范的实现和普及,第三方的模块化实现将会慢慢的淘汰。
AMD是非同步加载模块,允许函数回调,如Require.js,需提前加载所有模块。
CMD是按需加载模块的(可以依赖就近),不需要在模块开始就加载所有依赖。
AMD和CMD 规范 模块加载区别:前者是对于依赖的模块提前执行,后者是延迟执行。前者提倡依赖前置,后者提倡依赖就近,只需要在用到某个模块时再require.
// AMD
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 注意标红的,通过函数回调的方式将引入的依赖赋值给标红的变量,然后整个块就可以利用这个引入的依赖了
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
});
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b')
// 依赖可以就近书写
b.doSomething()
// ...
});
JavaScript 模块化主要有三种方案:
1.CommonJS
// module math.js
module.exports = function add (a, b) { return a + b; } // main.js
var {add} = require('./math'); console.log('1 + 2 = ' + add(1,2);
2.AMD / CMD
// module add.js
define(function () {
return {
add: function (a, b) add { return a + b; }
};
}); // main.js
require(['add'], function (add) { console.log('1 + 2 = ' + add(1,2);
});
3.ES6
// module add.js
export function add (a, b) { return a + b; } // main.js
import {add} from 'add.js';
之前的几种模块化方案都是前端社区自己实现的,只是得到了大家的认可和广泛使用,而ES6的模块化方案是真正的规范。 在ES6中,我们可以使用 import 关键字引入模块,通过 export 关键字导出模块,功能较之于前几个方案更为强大,也是我们所推崇的,但是由于ES6目前无法在浏览器中执行,所以,我们只能通过babel将不被支持的import编译为当前受到广泛支持的 require。
之前在想这个问题之前,一直有个疑问,浏览器怎么支持的require,exports, module, define 这些字段的? 。。。
很二逼的疑问,因为 require.js sea.js 就是用来支持浏览器提供这些字段的,也就是说在我们自己编写的模块之前需要先引入这些规范实现的库文件
<script src="./require.js"></script>
<script src="./otherModule.js"></script>
参考链接:https://www.jianshu.com/p/3832c00a44a7
http://www.ruanyifeng.com/blog/2015/05/commonjs-in-browser.html
JavaScript 模块化的更多相关文章
- Javascript模块化编程(三):require.js的用法
Javascript模块化编程(三):require.js的用法 原文地址:http://www.ruanyifeng.com/blog/2012/11/require_js.html 作者: 阮一峰 ...
- Javascript模块化编程(二):AMD规范
Javascript模块化编程(二):AMD规范 作者: 阮一峰 原文地址:http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_d ...
- Javascript模块化编程(一):模块的写法
Javascript模块化编程(一):模块的写法 作者: 阮一峰 原文链接:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html ...
- Javascript模块化编程(二):AMD规范(转)
这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为有了模块,我们就可以更方便地使用别人的代码,想要 ...
- Javascript模块化编程(一):模块的写法(转)
随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂. 网页越来越像桌面程序,需要一个团队分工协作.进度管理.单元测试等等......开发者 ...
- Javascript模块化规范
Javascript模块化规范 一.前端js模块化由来与演变 CommonJS 原来叫 ServerJS,推出 Modules/1.0 规范后,在 Node.js 等环境下取得了很不错的实践.09年下 ...
- Javascript模块化开发,使用模块化脚本加载工具RequireJS,提高你代码的速度和质量。
随着前端JavaScript代码越来越重,如何组织JavaScript代码变得非常重要,好的组织方式,可以让别人和自己很好的理解代码,也便于维护和测试.模块化是一种非常好的代码组织方式,本文试着对Ja ...
- Javascript 模块化开发上线解决方案
最近又换部门了,好频繁地说...于是把这段时间搞的小工具们简单整理了一下,作了一个小的总结.这次用一个简单业务demo来向大家介绍一下Javascript模块化开发的方式和自动化合并压缩的一些自己的处 ...
- Javascript模块化编程(二):AMD规范 作者: 阮一峰
声明:转载自阮一峰的网络日志 这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为有了模块,我们就可 ...
- Javascript模块化编程(一):模块的写法 作者: 阮一峰
声明:转载自阮一峰的网络日志 随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂. 网页越来越像桌面程序,需要一个团队分工协作.进度管理. ...
随机推荐
- Oracle中查询表中数据的上次更新时间
目前找到的是以下方式,但是这种方式在表的数据量比较大的时候效率会比较慢. select to_char(scn_to_timestamp(max(ora_rowscn)),'YYYY-MM-DD HH ...
- 【好好补题,因为没准题目还会再出第三遍!!】ACM字符串-组合数学(官方题解是数位DP来写)
ACM字符串 .长度不能超过n .字符串中仅包含大写字母 .生成的字符串必须包含字符串“ACM”,ACM字符串要求连在一块! ok,是不是很简单?现在告诉你n的值,你来告诉我这样的字符串有多少个 输入 ...
- 揭秘PHP深受Web开发者喜爱的原因
我们再次回顾一下在软件开发的发展中非常有名的技术"PHP"(Hypertext Pre-Processor),它是由Rasmus Lerdorf在1995年发明的.开始阶段,PHP ...
- Object类实现的方法
---恢复内容开始--- 1.Clone 对象浅复制,实现Clonable接口可调用,否则CloneNotSupportedException异常 2.getClass final方法,获得方法运行的 ...
- python_datetime模块和time模块
1.datetime模块 获取当前时间: import datetime # 获取当前时间 ctime = datetime.datetime.now() print(ctime) 只显示:年-月-日 ...
- SSH自动断开处理
解决ssh登录后闲置时间过长而断开连接 时我们通过终端连接服务器时,当鼠标和键盘长时间不操作,服务器就会自动断开连接,我们还的需要重新连接,感觉很麻烦,总结一下解决此问题的方法 方法一. 修改/etc ...
- 010_Linux驱动之_DECLARE_WAIT_QUEUE_HEAD函数
1. 功能:创建以个等待队列头 2. 函数原型 #define DECLARE_WAIT_QUEUE_HEAD (name) / wait ...
- 019_linux驱动之_定时器的引入
(一)定义一个timer_list定时器结构体,linux 内核定时器 timer_list详解 (二)初始化定时器,当超时时间expires到之后会调用buttons_timer_function函 ...
- 013_使用 user.txt 文件中的人员名单,在计算机中自动创建对应的账户并配置初始密码
for i in `cat user.txt`do useradd $i echo "123456" | passwd --stdin $idone
- Linux之基础命令
常用命令 查看ip地址的两种方式 ifconfig ip addr show Linux的两种ip地址: 127.0.0.1 本机回环地址 0.0.0.0 全网地址/绑定所有网卡/所有地址 Linux ...