前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于前端开发中的模块化

关于前端开发中的模块化

作者头像
LIYI
发布2019-09-02 15:38:15
7320
发布2019-09-02 15:38:15
举报
文章被收录于专栏:艺述论专栏

前端开发离不开模块化,与模块化有关的关键字有以下几个:

  • require/module.exports
  • export/import
  • define/require/exprots
  • define/seajs.use

这涉及到4种模块化规范:AMD、CMD、CommonJS、ES6。

AngularJS

AngularJS模块化使用的并不是标准的AMD规范,AngularJS的风格风格大致是这样的:

不仅模块的定义和引入麻烦,与Html标签耦合也较严重,阅读吃力,扩展与复用麻烦。AngularJS的模块化风格还停留在代码层面。

后来出现了AMD规范。

AMD

AMD规范使用统一的define、require做为伪关键字。模块化定义是这样的:

代码语言:javascript
复制
// a.js
define(["b", "require", "exports"], function(b, require, exports) {
    console.log("a.js执行");
    console.log(b);
    // 暴露api可以使用exports、module.exports、return
    exports.a = function() {
        return require("b");
    }
})
// b.js
define(function() {
    console.log('b.js执行');
    console.log(require);
    console.log(exports);
    console.log(module);
    return 'b';
})

引用是这样的:

代码语言:javascript
复制
// index.js
require(['a', 'b'], function(a, b) {
    console.log('index.js执行');
})

define与require虽然不是语法关键字,但已经在努力让自己看起来是关键字了,它们依赖于requireJS才能工作。AMD规范仍然是在代码层面折腾。

再后来出现了CMD规范。

CMD

CMD(Common Module Definition)表示通用模块定义,该规范是国内发展出来的,由阿里的玉伯提出。就像AMD有个requireJS,CMD有个浏览器的实现SeaJS。

定义模块:

代码语言:javascript
复制
// mymodule.js
define(function(require, exports, module) {
  var $ = require('jquery.js')
  $('div').addClass('active');
});

加载模块:

代码语言:javascript
复制
// 加载与使用模块
seajs.use(['mymodule.js'], function(my){
});

无论是AMD、还是CMD都是在文件内的代码层面折腾。后来出现了CommonJS,从CommonJS开始,默认一个文件是一个模块。

CommonJS

定义模块:

代码语言:javascript
复制
// foo.js
function foo(){
    lib.log('hello world!');
}
 
// 导出给其它模块
module.exports.foo = foo;

使用模块:

代码语言:javascript
复制
const foo = require('foo');

CommonJS规范已经相当完善了。微信小程序、小游戏默认推荐的模块化规范即是CommonJS。

模块的动态加载与静态加载

使用CommonJS,可以在运行时动态加载模块:

代码语言:javascript
复制
if (condition) {
  let my = require('./mymodual')
}

但是动态加载不便于引擎静态分析,不能在开发阶段就确认程序的依赖关系。此外,像这样的引入:

代码语言:javascript
复制
let { stat, exists, readFile } = require('fs');

这是整体引入了fs,然后分别赋值给了三个变量。等价于:

代码语言:javascript
复制
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;

为了实现按需引入及在开发阶段尽早确认类库的依赖关系,尽量减少运行时异常。ES6模块规范应运而生。

ES2015(ES6)

2015年6月,ES2015正式发布,即ES6。

声明模块:

代码语言:javascript
复制
export function area(radius) {
  return Math.PI * radius * radius;
}

引用与使用模块:

代码语言:javascript
复制
import {area} from './circle'
console.log('圆面积:' + area(10))

如果想在引入时不使用析造语法,声明模块时可以使用default关键字:

代码语言:javascript
复制
export default function area(radius) {
  return Math.PI * radius * radius;
}

引用就这样了,不再需要花括号:

代码语言:javascript
复制
import area from './circle'

统一的导出格式

一个类库,有没有可能同时遵从多个模块化规范,支持多种方式的导入?

答案是可以的:

代码语言:javascript
复制
;(function (name, definition) {
  // 检测上下文环境是否为AMD或CMD
  var hasDefine = typeof define === 'function',
      // 检查上下文环境是否为Node
      hasExports = typeof module !== 'undefined' && module.exports;

  if (hasDefine) {
    // AMD环境或CMD环境
    define(definition);
  } else if (hasExports) {
    // 定义为普通Node模块,使用CommonJS规范导出
    module.exports = definition();
  } else {
    // 将模块的执行结果挂在window变量中,在浏览器中this指向window对象
    // 使用script标签在html中引入
    this[name] = definition();
  }
})('hello', function () {
  // 真正的模块代码放在这里
  'use strict';
  /*eslint-disable */
  var hello = function () {};
  return hello;
});

这里导出方式,不但支持以上4种模块化方案,还支持传统的script标签引入。当以script标签在html页面中引入时,访问window.xxx可以调取类库。例如上面的示例,直接以script引入,可以访问window.hello。

use strict是开启严格模式。开启后,对代码有如下约束:

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀 0 表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • eval和arguments不能被重新赋值
  • arguments不会自动反映函数参数的变化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局对象
  • 不能使用fn.caller和fn.arguments获取函数调用的堆栈
  • 增加了保留字(比如protected、static和interface)

2019年5月10日 石桥码农

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 艺述论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AngularJS
  • AMD
  • CMD
  • CommonJS
  • 模块的动态加载与静态加载
  • ES2015(ES6)
  • 统一的导出格式
相关产品与服务
命令行工具
腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档