当项目越来越大时,会遇到一些问题:

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 模块化的更多相关文章

  1. Javascript模块化编程(三):require.js的用法

    Javascript模块化编程(三):require.js的用法 原文地址:http://www.ruanyifeng.com/blog/2012/11/require_js.html 作者: 阮一峰 ...

  2. Javascript模块化编程(二):AMD规范

    Javascript模块化编程(二):AMD规范   作者: 阮一峰 原文地址:http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_d ...

  3. Javascript模块化编程(一):模块的写法

    Javascript模块化编程(一):模块的写法 作者: 阮一峰 原文链接:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html ...

  4. Javascript模块化编程(二):AMD规范(转)

    这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为有了模块,我们就可以更方便地使用别人的代码,想要 ...

  5. Javascript模块化编程(一):模块的写法(转)

    随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂. 网页越来越像桌面程序,需要一个团队分工协作.进度管理.单元测试等等......开发者 ...

  6. Javascript模块化规范

    Javascript模块化规范 一.前端js模块化由来与演变 CommonJS 原来叫 ServerJS,推出 Modules/1.0 规范后,在 Node.js 等环境下取得了很不错的实践.09年下 ...

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

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

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

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

  9. Javascript模块化编程(二):AMD规范 作者: 阮一峰

    声明:转载自阮一峰的网络日志 这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为有了模块,我们就可 ...

  10. Javascript模块化编程(一):模块的写法 作者: 阮一峰

    声明:转载自阮一峰的网络日志 随着网站逐渐变成"互联网应用程序",嵌入网页的Javascript代码越来越庞大,越来越复杂. 网页越来越像桌面程序,需要一个团队分工协作.进度管理. ...

随机推荐

  1. Centos7下安装Elasticsearch 5.6.6

    环境 因为elasticsearch是用java编写的,所以需要先安装JDK ES 5,安装需要 JDK 8 以上ES 6.5,安装需要 JDK 11 以上ES 7.2.1,内置了 JDK 12 安装 ...

  2. 使用java中的反射获得object对象的属性值

    知识点:使用java中的反射获得object对象的属性值 一:场景 这两天开发代码时,调用别人的后台接口,返回值为Object对象(json形式的),我想获得object中指定的属性值,没有对应的ge ...

  3. Controllers返回View的一个完整流程

    详细说明一个MVC框架下,返回一个view的原理.如下图: 上图粗略的说明了一个返回View的流程,细节如下: 1.定义Model类: 2.定义接口添加接口约束为class: 3.定义接口实现类,即对 ...

  4. ios滑动回弹效果导致的穿透问题

    1 给样式中去除掉下面的css样式 -webkit-overflow-scrolling:touch;/* 当手指从触摸屏上移开,会保持一段时间的滚动 */ -webkit-overflow-scro ...

  5. Python sleep()函数用法:线程睡眠

    如果需要让当前正在执行的线程暂停一段时间,并进入阻塞状态,则可以通过调用 time 模块的 sleep(secs) 函数来实现.该函数可指定一个 secs 参数,用于指定线程阻塞多少秒. 当前线程调用 ...

  6. node.js中允许的app对象声明方式

    伪对象形式 app = function () { console.log("我是一个初始化的app对象"); }; app.get=function () { console.l ...

  7. partial 部分类

    partial 关键字允许把类.结构.方法或接口放在多个文件中.一般情况下,一个类全部驻留在单个文件中.但有时,多个开发人员需要访问同一个类,或者某种类型的代码生成器生成了一个类的某部分,所以把类放在 ...

  8. python--第六天练习题

    #1.正则表达式计算 origin = "1 - 2 * ( ( 60 - 30 + ( -40.0 / 5 ) * ( 9 - 2 * 5 / 3 + 7 / 3 * 99 / 4 * 2 ...

  9. java监测硬盘空间大小

    package com.zuidaima.util.file; import java.io.File; public class FreeDiskSpace { public static void ...

  10. AtCoder Beginner Contest 132

    目录 Contest Info Solutions A. Fifty-Fifty B. Ordinary Number C. Divide the Problems D. Blue and Red B ...