跳至主要內容

JavaScript

LincZero大约 3 分钟

JavaScript

目录

模块系统

为什么要模块化

模块化 vs 旧模块化

为什么要模块化?

<script>标签引入js脚本:全局变量同名冲突问题、引用脚本顺序问题

解决方案

  • 解决方案v1:匿名函数闭包,但变量变得不可引用,代码不可复用
  • 解决方案v2:匿名函数闭合的同时,返回一个值给对象实例
  • 解决方案v3:模块化规范ES6 √

常用的模块化规范

  • CommonJS
  • AMD
  • CMD
  • ES6的Modules(不再需要闭包,文件就是模块)

模块化进化史

(1) 最早全写在js

function foo(){/*...*/}
function bar(){/*...*/}

// 原始写法
// 缺点:耦合度高,不方便管理。Global被污染,容易命名冲突

(2) 对象封装【Namespace模型】

(划分私有命名空间)

var myapp = {
    foo:function(){}
    bar:function(){}
}
myapp.foo();

// 解决:把变量的范围局限在对象里面
// 优点:减少Global变量数目
// 缺点:对象里的属性和方法很容易被修改掉,不安全

(3) 匿名闭包、立即执行函数【IIFF模型】

(划分私有命名空间)

(function(){
    var foo = 111;
    var bar = function () { return 222 }
    return { bar: bar }
})();

// 解决:匿名函数闭包(将add的私有化到calculator中)
// 优点:可以保护好里面的属性和方法
// 缺点:不可调用内部函数、变量,无复用性

(4) 改进:使用模块作为出口

// ——————File_A:
var modeleA=(function(){
    var foo = 111;
    var bar = function () { return 222 }
    return { bar: bar }
})();
// ——————File_B:
modeleA.bar(); // 222
modeleA.foo;  // underfined

// 模块化基本封装,模块化雏形

模块化规范

服务器端规范
    【CommonJS】√   Nodejs、webpack     遵循CommonJS规范

浏览器端规范
    【AMD】         RequireJS   遵循AMD规范
    【CMD】         SeaJS       遵循CMD规范

ALL
    【ES6 module】√
  • 模块化核心:导入和导出

  • 模块功能

    • 暴露部分接口给外部
    • 划分作用域
  • 具体实现

    • CommonJS

      module.exports = {
          flag: true,
          test(a, b) {}
      }
      
  • 前端三大框架

    • Angular
      • 09年诞生
      • 让开发单页更方便
      • 主要为前端带来 MVVM 开发模式,即数据驱动视图,不操作 DOM
    • React
      • Facebook开发
      • 组件化
    • Vue
      • Vue作者:尤雨溪(华裔),早期由个人开发
  • js模块化

    • js本身不支持模块化
      require
      exports
      Node.js
      node中对js进行了特殊的模块化支持 CommonJS
      
      php可以直接'require', 'include'
      可以使用API来进行文件与文件之间的依赖加载
      
      浏览器也可以像node模块一样编程
      '<script>'
      require.js  AMD
      sea.js      CMD
      

使用 - CommonJS

环境

CommonJS要在webpack里写(webpack依赖于node)
不然没有底层的东西去解析这个结构

导出

// multiple:
    module.exports.foo = 'foo'  // exports.foo = 'foo'
    module.exports.app = 'app'  // exports.app = 'app'
    // 或
    module.exports = {
        foo = 'foo',  // foo: foo,  // foo,
        app = 'app'  // app: app   // app
    }

// Single:
    module.exports = 'foo'

导入

const aaa = require('./aaa.js')
var flag = aaa.flag
var sum = aaa.sum
// 或
const {flag, sum} = require('./aaa.js')

使用 - ES6

载入(html里载入)

<script src="aaa.js" type="module"></script>
// html里导入,加module类型就不会有命名冲突

导出

export var flag = 100
export function sum () {}
export class Person {}  // ES6的类
// 或
export {
    flag,  // flag: flag,
    sum    // sum: sum
}
// 或
export default [function () {}]  // 只能有一个,无须加名字

导入(js里引用)

import {flag,sum} from './aaa.js'
// 或
import flag from './aaa.js'
// 或(全部导入) 
import * as aaa from './aaa.js'   // 用aaa.flag调用

使用

模块与导包

(原生不支持模块化,Nodejs(ES6)提供支持)

const express = require("express")