js模块化

2019-12-12  本文已影响0人  Ni_c746

# js模块化

**JavaScript本身是不支持模块化的,只不过后来一些社区的大佬制定了一个模块规范,主要分为两种,一个是用于服务器的CommonJs,另一种用于客户端的AMD(比如requireJs)、CMD(比如seaJs)。后来ES6提供了通用的模块化方案**

## 1.AMD(requireJs) 

在ES6出现之前,JS不像其他语言同样拥有“模块”这一概念,于是为了支持JS模块化,出现了各种各样的语言工具,如ReuqireJS。 

``` 

<!--require.html--> 

<!DOCTYPE html> 

<html> 

<head> 

<title>requirejs学习</title> 

</head> 

<body> 

<script src='./js/require.js'></script> 

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

<script> 

require(['people'], function (people) { 

people.say('Neol'); 

}) 

require(['cat'], function (people) { 

people.say(); 

}) 

</script> 

</body> 

</html> 

``` 

``` 

// ./js/config.js 

require.config({ 

//默认情况下从这个文件开始拉去取资源 

baseUrl:'./js/', 

path: { 

'jquery': './js/jquery.js' 

}); 

``` 

``` 

// ./js/people.js 

define(['jquery'], function() { 

return { 

say: function say(name){ 

console.log('I am ' + name, $); 

}); 

``` 

``` 

// ./js/cat.js 

define([], function() { 

return { 

say: function say(){ 

console.log('喵喵喵~'); 

}); 

``` 

特点: 

* js、jquery可以直接使用 

## 2.CMD(seaJs) 

SeaJS 是一个适用于 Web 浏览器端的模块加载器。使用 SeaJS,可以更好地组织 JavaScript 代码。 

``` 

<!--seajs.html--> 

<!doctype html> 

<html lang="en"> 

<head> 

<meta charset="UTF-8"/> 

<title>seajs入门实例</title> 

</head> 

<body> 

<div id="hello">132456798</div> 

</body> 

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

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

<script> 

// 加载入口文件 

seajs.use(['./js/hello'], function(hello) { 

$('#hello').click(function(){ 

hello() 

}) 

}); 

</script> 

</html> 

``` 

``` 

// config.js 

seajs.config({ 

base: './js/', 

path: { 

'jquery': './js/jquery.js' 

}); 

``` 

``` 

// hello.js 

define(function(require, exports, module) { 

require('jquery'); 

module.exports = function () { 

$('#hello').toggle('slow'); 

}); 

``` 

特点: 

* js、jquery可以直接使用

## 3.es6模块化 

``` 

// 1.js 

export const a = 1; 

export const b = 2; 

// 2.js 

import {a, b} from './1.js'; 

``` 

``` 

// 1.js 

const a = 1; 

const b = 2 

export {a, b} 

// 2.js 

import {a, b} from './1.js'; 

// 3.js 

import * as obj from './1.js'; 

``` 

``` 

// 1.js 

const a = 1; 

export default a; 

// 2.js 

import obj from './1.js'; 

``` 

``` 

// 1.js 

import('./2.js').then(res =>{ 

console.log(res); 

}); 

``` 

特点: 

* 每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件,直接从内存中读取。 一个模块就是一个单例,或者说就是一个对象; 

* 每一个模块内声明的变量都是局部变量, 不会污染全局作用域; 

* 模块内部的变量或者函数可以通过export导出; 

* 一个模块可以导入别的模块 

* export能有多个,但是export default只能有一个。 

缺点:需要支持es6,或者使用babel.js转换。 

结论:用在有webpack可以配置babel的项目,不用在jquery项目。

## 4.浏览器中的 ES6 module 实现

```

  <script type="module">

        import { alert_msg } from './utils.js'

        alert_msg('123456789')

    </script>

    // 使用 `nomodule` 属性向后兼容

    <script nomodule src="fallback.js"></script>

```

```

// utils.js

export function alert_msg (text) {

    alert(text)

}

```

特点:

* 浏览器加载 ES6 模块,也使用`<script>`标签,但是要加入`type="module"`属性;type="module" 等同于打开了`<script>`标签的`defer`属性

* 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见

* 模块脚本自动采用严格模式,不管有没有声明`use strict`

* 模块之中,可以使用`import`命令加载其他模块(`.js`后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用`export`命令输出对外接口

* 模块之中,顶层的`this`关键字返回`undefined`,而不是指向`window`。也就是说,在模块顶层使用`this`关键字,是无意义的

* 同一个模块如果加载多次,将只执行一次

* 利用顶层的`this`等于`undefined`这个语法点,可以侦测当前代码是否在 ES6 模块之中

缺点:兼容性不足

![image.png](./upload/201912/11/1576045913604281624.png)

结论:不要用

## 5.CommonJS

根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。所以,定义一个模块就是写一个新的js文件,但是最后要将文件的内容exports出来。接下来我们看一下如何定义模块和加载模块。

```

//定义一个module.js文件 

var A = function() { 

console.log('我是定义的模块'); 

//导出这个模块 

//1.第一种返回方式 module.exports = A; 

//2.第二种返回方式 module.exports.test = A 

//3.第三种返回方式 exports.test = A; 

exports.test = A; 

//再写一个test.js文件,去调用刚才定义好的模块,这两个文件在同一个目录下 

var module = require("./module");  //加载这个模块 

//调用这个模块,不同的返回方式用不同的方式调用 

//1.第一种调用方式 module(); 

//2.第二种调用方式 module.test(); 

//3.第三种调用方式 module.test(); 

module.test(); 

//接下来我们去执行这个文件,前提是你本地要安装node.js,不多说了,自己百度安装。 

//首先打开cmd, cd到这两个文件所在的目录下,执行: node test.js 

node test.js 

//输出结果:我是定义的模块

```

特点:

* 模块化:模块化就是将不同功能的函数封装起来,并提供使用接口,他们彼此之间互不影响。 

* 不会阻塞页面:RequireJS,会在相关的js加载后执行回调函数,这个过程是异步的,所以它不会阻塞页面。 

* 按需加载:平时我们写html文件的时候,在底部可能会引用一堆js文件。在页面加载的时候,这些js也会全部加载。使用require.js就能避免此问题。举个例子,比如说我写了一个点击事件,放到了一个js文件里,并在html引用,在不使用require.js的情况下,页面加载它跟着加载,使用后则是什么时候触发点击事件,什么时候才会加载js。

缺点:

* 只能用在node服务端。

[.zip](./upload/201912/11/15760622351371730206.zip)

上一篇下一篇

猜你喜欢

热点阅读