JavaScript 模块化


JavaScript起初没有官方的模块语法
在社区中诞生了野生规范:

  • AMD —— 最古老的模块系统之一,最初由 require.js 库实现。
  • CommonJS —— 为 Node.js 服务器创建的模块系统。
  • UMD —— 另外一个模块系统,建议作为通用的模块系统,它与 AMD 和 CommonJS 都兼容。

ComonJs

CommonJS的核心思想就是通过 require 方法来同步加载所要依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口。如下所示:

// a.js
let x = 5;
let addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

//b.js
let a = require('./a.js');
console.log(a.x); //5
console.log(a.addX(3)); //8 

exports是对module.exports的引用,用法一样,如果有重名时以module.exports为准

  1. 通过require引入基础数据类型时,属于复制该变量
  2. 通过require引入复杂数据类型时,浅拷贝该对象(指向同一个对象)
  3. 出现模块之间的循环引用时,会输出已经执行的模块,而未执行的模块不输出
    3可以看:https://www.cnblogs.com/unclekeith/p/7679503.html

ES6模块

ES6引入了模块功能

  • export 关键字标记了可以从当前模块外部访问的变量和函数
  • import 关键字允许从其他模块导入功能

由于模块支持特殊的关键字和功能,因此我们必须通过使用 <script type="module"> 特性(attribute)来告诉浏览器,此脚本应该被当作模块(module)来对待。

  <!doctype html>
  <script src="./test.js" type="module"></script> // 加了type="module" 就不是全局变量了
  
  //test.js
    import {sayHi} from './say.js';
    document.body.innerHTML = sayHi('John');
  //say.js
    export function sayHi(name){
      return "hello "+name;
    }

功能

模块和常规脚本相比的不同

始终使用"use strict"

模块默认使用严格模式,未声明的变量赋值会报错

<script type="module">
  a = 5; // error
</script>

模块级作用域

常规的<script>引用所有代码都在同一个全局作用域中
而每个模块有自己的作用域,一个模块中的变量和函数在其他脚本是不可见的

//index.html
<!doctype html>
<script type="module" src="a.js"></script>
<script type="module" src="b.js"></script>

//a.js
let a = 1;

//b.js
alert(a); // 报错

浏览器中,每个 <script type="module">也存在独立的顶级作用域

<script type="module">
  // 变量仅在这个 module script 内可见
  let user = "John";
</script>

<script type="module">
  alert(user); // Error: user is not defined
</script>

正确应该用export导出想被外部访问的内容,并import所需要的内容,后面导入导出再细说

模块代码仅在第一次导入时被解析

模块只执行一次,如果同一个模块被导入到多个其他位置,那它的代码仅会在第一次导入时执行,然后将导出的内容提供给其他所有导入

// admin.js
export let admin = {
  name: "小红"
}

// a.js
import {admin} from './admin.js'
admin.name = '小李'

// b.js
import {admin} from './admin.js'
console.log(admin); // 小李

所以模块只执行了一次,生成导出并分享给了其他导入,某个地方修改后其他模块也能看到
我们可以在首次导入时初始化设置模块,只需要设置一次后其他导入就都可以直接使用了

在一个模块中,"this"是undefined

<script>
  console.log(this); // window
</script>

<script type="module">
  conso.log(this); // undefined
</script>

模块脚本是延迟的

等同于使用了defer,即

  • 下载外部模块脚本

eg.

<script type="module">
  alert(typeof button); // object:脚本可以“看见”下面的 button
  // 因为模块是被延迟的(deferred,所以模块脚本会在整个页面加载完成后才运行
</script>

<!-- 相较于下面这个常规脚本: -->

<script>
  alert(typeof button); // button 为 undefined,脚本看不到下面的元素
  // 常规脚本会立即运行,常规脚本的运行是在在处理页面的其余部分之前进行的
</script>

<button id="button">Button</button>

第二个脚本要优先于第一个脚本执行,模块脚本是被延迟的要等到HTML文档被处理完才会执行,而常规脚本则会立即运行

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值