模块化

模块化

模块是实现特定功能的一组方法,模块化是一种规范、一种约束,这种约束会大大提升开发效率。JS模块化思想是将每个JS文件看作是一个模块,每个模块通过固定的方式引入,并且通过固定的方式向外暴露指定的内容。

函数封装

function fn1(){
    statement
}

function fn2(){
    statement
}

对象

var myModule = {
    var1: 1,

    var2: 2,

    fn1: function(){

    },

    fn2: function(){

    }
}

AMD和RequireJS

RequireJs是JS模块化的工具框架,是AMD规范的具体实现。但是有意思的是,RequireJs诞生之后,推广过程中产生的AMD规范。RequireJs的优点:1)动态并行加载js,依赖前置,无需再考虑js加载顺序问题;2)核心还是注入变量的沙箱编译,解决模块化问题;3)规范化输入输出,使用起来方便;4)对于不满足AMD规范的文件可以很好地兼容。

require方式(AMD模式)

test.js
 
// 首先使用define进行定义
define(function(){
    function fun1(){
      alert("it works");
    }
    fun1();
})
 
// 在页面中使用require进行引用
require(["js/a"]);

requireJs 的问题在于,加在一个模块时,会预先加载该模块的所有依赖模块,但是这些依赖很可能一开始并不用到。同时依赖写起来一长串,也很麻烦。比较好的是 AMD 保留了 commonJs 中的 require、exprots、module3 个功能,可以不把以来都写在 dependencies 中,而是在需要时使用 require 引入。

AMD是’‘AsynchronousModuleDefinition’‘的缩写,意思就是’‘异步模块定义’’。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到所有依赖加载完成之后(前置依赖),这个回调函数才会运行。

define() 函数

AMD规范只定义了一个函数 define,它是全局变量。函数的描述为:

define([module-name?],[array-of-dependencies?],[module-factory-or-object]);         
  • module-name:模块标识,可以省略
  • array-of-dependencies:所依赖的模块数组,可以省略
  • module-factory-or-object:模块的实现或者一个 JavaScript 对象
    define 函数具有异步性,其首先会异步加载第二个参数中列出的依赖模块,当所有的模块被加载后,执行第三个参数的回调函数。
define 函数使用
define(function(){
    var a = require("A");
})

define函数在执行的时候,会调用函数的 toString 方法,并扫描其中的 require 调用,提前载入这些模块,载入完成后再执行。

define("A", ["require", "exports"], function(require, exports){
    export.fun = function(){
        return require("B").fun;
    }
});

require 函数是用来模块依赖,即获取模块的引用,即使模块没有作为参数定义,也能够被使用;exports 定义 A 模块实体,在其上定义的任何属性和方法就是 A 模块的属性和方法。通过 exports.fun= … 就是为 A 模块定义了一个 fun 方法。

CMD

CMD规范说明:

Common Module Definition(通用模块定义)
专用于浏览器端,模的加载是异步的
模块使用时才会加载执行

CMD基本语法:

定义暴露模块:

//定义没有依赖的模块
define(function(require, exports, module){
  exports.xxx = value
  module.exports = value
})
//定义有依赖的模块
define(function(require, exports, module){
  //引入依赖模块(同步)
  var module2 = require('./module2')
  //引入依赖模块(异步)
    require.async('./module3', function (m3) {
    })
  //暴露模块
  exports.xxx = value
})

引入使用模块:

define(function (require) {
  var m1 = require('./module1')
  var m4 = require('./module4')
  m1.show()
  m4.show()
})

sea.js

Sea.js 追求简单、自然的代码书写和组织方式,具有以下核心特性:

  • 简单友好的模块定义规范:Sea.js 遵循 CMD 规范,可以像 Node.js 一般书写模块代码。
  • 自然直观的代码组织方式:依赖的自动加载、配置的简洁清晰,可以让我们更多地享受编码的乐趣。

Sea.js 还提供常用插件,非常有助于开发调试和性能优化,并具有丰富的可扩展接口。

加载模块

SeaJS提供了seajs.use来加载模块

语法:

seajs.use([dependencies], function(){})

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <script src="sea.js"></script>
        <script src="cmd2.js"></script>
        <script src="cmd1.js"></script>
        <script type="text/javascript">
            seajs.use(['cmd2.js','cmd1.js'],function(cmd2,cmd1){
                // ....
            })
        </script>
    </body>
</html>

CommonJS

浏览器不兼容CommonJS的根本原因,在于缺少四个Node.js环境的变量。

  • module
  • exports
  • require
  • global

只要能够提供这四个变量,浏览器就能加载 CommonJS 模块。

下面是一个简单的示例。

var module = {
exports: {}
};

(function(module, exports) {
exports.multiply = function (n) { return n * 1000 };
}(module, module.exports))

var f = module.exports.multiply;
f(5) // 5000 

上面代码向一个立即执行函数提供 module 和 exports 两个外部变量,模块就放在这个立即执行函数里面。模块的输出值放在 module.exports 之中,这样就实现了模块的加载。

CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

上面代码通过module.exports输出变量x和函数addX

CommonJS模块的特点如下。

  • 所有代码都运行在模块作用域,不会污染全局作用域。
  • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  • 模块加载的顺序,按照其在代码中出现的顺序。

ES6 模块化

es6模块基本用法

es6中新增了两个命令export和import,export命令用于规定es6模块的对外接口,import 命令用于输入其他es6模块化提供的功能。

一个es6模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个 变量, 就必须使用export关键字输出该变量。下面是一个JS文件,里面使用export命令输出变量。

export const add = function (a, b) {
    return a + b
}
export const subtract = function (a, b) {
    return a - b
}

使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)。

import { add, subtract } from './test.js'

add(1, 2)
substract(3, 2)
es6 export详细用法

export 不止可以导出函数,还可以导出对象,类,字符串等等

export const obj = {
    test1: ''
}

export const test = ''

export class Test {
    constructor() {
    }
}

export的写法,除了像上面这样,还有另外一种。

let a = 1
let b = 2
let c = 3
export {
    a,
    b,
    c
}

上面代码在export命令后面,使用大括号指定所要输出的一组变量。它与前一种写法是等价的,但是应该优先考虑使用这种写法。因为这样就可以在脚本尾部,一眼看清楚输出了哪些变量。

通过 as 改变输出名称

// test.js
let a = 1
let b = 2
let c = 3
export {
    a as test,
    b,
    c
}
import { test, b, c} from './test.js'

上面啊的写法中,import 中需要指定加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。

export default 指定默认输出, import 无需知道变量名就可以直接使用

export default function () {
    console.log('hello world')
}
import say from './test.js' 
say()

有了export default命令,加载模块时就非常直观了,以一些常用的模块为例

import $ from 'jQuery'
import _ from 'lodash'
import moment from 'moment'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值