资讯专栏INFORMATION COLUMN

前端模块化规范笔记

honmaple / 1664人阅读

摘要:目前通行的的模板规范共有两种和的模块系统,是参照规范实现的即为服务器端模块的规范。规范则是非同步加载模块,允许指定回调函数。

目前通行的Javascript的模板规范共有两种:CommonJSAMD commonjs

nodejs的模块系统,是参照commonjs规范实现的

commonjs即为服务器端模块的规范。 commonjs的规范: 根据commonjs规范,一个多带带的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象

commonjs模块的加载原理

commonjs模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。

AMD

commonjs规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以commonjs规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。

可以理解为AMD即为能在客户端环境,并且能兼容服务器端模块的一种模块规范

AMD的模块定义:
AMD规范使用define方法定义模块

Define第一个参数表达依赖的模块数组,第二个为加载完依赖的模块数组后,模块执行的函数

AMD的模块加载定义:跟commonjs一样,AMD也采用require()语句来加载模块,但是与commonjs不同的是,它要求有两个参数:
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数

AMDCMD对比

对于依赖的模块,AMD是提前执行,CMD是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD推崇 as lazy as possible.

CMD推崇依赖就近,AMD推崇依赖前置

AMDAPI默认是一个当多个用,CMD的API 严格区分,推崇职责单一。比如AMD里,require分全局require和局部require,都叫requireCMD里,没有全局 require,而是根据模块系统的完备性,提供seajs.use来实现模块系统的加载启动。CMD里,每个API都简单纯粹。

ES6 Modules

ES6模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。commonjsAMD模块,都只能在运行时确定这些东西。比如,commonjs模块就是对象,输入时必须查找对象属性。

// CommonJS模块
let { stat, exists, readFile } = require("fs");

// 等同于
let _fs = require("fs");
let stat = _fs.stat, exists = _fs.exists, readfile = _fs.readfile;

上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取3个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。

ES6模块不是对象,而是通过export命令显式指定输出的代码,输入时也采用静态命令的形式。

// ES6模块
import { stat, exists, readFile } from "fs";

上面代码的实质是从fs模块加载3个方法,其他方法不加载。这种加载称为“编译时加载”,即ES6可以在编译时就完成模块加载,效率要比CommonJS模块的加载方式高。当然,这也导致了没法引用ES6模块本身,因为它不是对象。

由于ES6模块是编译时加载,使得静态分析成为可能。有了它,就能进一步拓宽JavaScript的语法,比如引入宏(macro)和类型检验(type system)这些只能靠静态分析实现的功能。

除了静态加载带来的各种好处,ES6模块还有以下好处。

不再需要UMD模块格式了,将来服务器和浏览器都会支持ES6模块格式。目前,通过各种工具库,其实已经做到了这一点。
将来浏览器的新API就能用模块格式提供,不再必要做成全局变量或者navigator对象的属性。
不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供。
浏览器使用ES6模块的语法如下。


上面代码在网页中插入一个模块foo.js,由于type属性设为module,所以浏览器知道这是一个ES6模块。

Node的默认模块格式是CommonJS,目前还没决定怎么支持ES6模块。所以,只能通过Babel这样的转码器,在Node里面使用ES6模块。

用法

export
优先考虑这种写法而不是一个一个的export

// profile.js
var firstName = "Michael";
var lastName = "Jackson";
var year = 1958;

export {firstName, lastName, year};

提供对外接口必须在接口名与模块内部变量之间保持一一对应关系

// 报错
function f() {}
export f;

// 正确
export function f() {};

// 正确
function f() {}
export {f};

最后,export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,下一节的import命令也是如此。这是因为处于条件代码块之中,就没法做静态优化了,违背了ES6模块的设计初衷。

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

// main.js

import {firstName, lastName, year} from "./profile";

function setName(element) {
  element.textContent = firstName + " " + lastName;
}

上面代码的import命令,就用于加载profile.js文件,并从中输入变量。import命令接受一个对象(用大括号表示),里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。

import { lastName as surname } from "./profile";

注意,import命令具有提升效果,会提升到整个模块的头部,首先执行。

ES6模块加载的实质

ES6模块加载的机制,与CommonJS模块完全不同。CommonJS模块输出的是一个值的拷贝,而ES6模块输出的是值的引用。
ES6的输入有点像Unix系统的“符号连接”,原始值变了,import输入的值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

参考资料

IMWEB团队博客
知乎问答
阮一峰老师的ES6教程

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86432.html

相关文章

  • webpack 学习笔记(一)

    摘要:引言最近在学习,发现好多知识点,之前一点都没有接触过,如等等。使用本地安装,会存于文件夹内与属性内,更方便项目文件迁移以及协同开发等情况。 引言 最近在学习webpack,发现好多知识点,之前一点都没有接触过,如babel、core-js、browserslist等等。以前习惯了使用cli构建项目,很多东西不用考虑,拿来就用,这样的码农是不会有能力提升的,必须了解更多的知识点,才能成为...

    zhangwang 评论0 收藏0
  • JS学习笔记 - 块化

    摘要:在开发大型的项目中,可能会使用到管理的模块化工具。说道,学习过的同学会比较熟悉,是服务器模块的规范,采用了这个规范。可能是未来模块化解决方案的首选。 本文章记录本人在学习 JavaScript 中理解到的一些东西,加深记忆和并且整理记录下来,方便之后的复习。 在开发大型的web项目中,可能会使用到管理js的模块化工具。但是在前端轮子漫天飞的时代。那一款js模块化工具真正适合我...

    CntChen 评论0 收藏0
  • CSS学习笔记(十六) CSS最佳实践之可维护性篇

    摘要:国内各大公司都已经投入使用,在一些常见的网站,如淘宝腾讯小米等移动站点,随处可见其踪影。变革之腾讯手机淘宝的设计与实现前端乱炖适配总结样式重置上文已提及,这里推荐阅读同学写的专题文章。 前言 CSS代码难维护众所皆知。 为一个元素设置样式的方式可以通过定义的class、定义的id、元素的标签名、元素的属性等选择器以及这些选择器的组合来实现; 作用于某个元素上的样式又可能来自单个样式规...

    newtrek 评论0 收藏0
  • CSS学习笔记(十六) CSS最佳实践之可维护性篇

    摘要:国内各大公司都已经投入使用,在一些常见的网站,如淘宝腾讯小米等移动站点,随处可见其踪影。变革之腾讯手机淘宝的设计与实现前端乱炖适配总结样式重置上文已提及,这里推荐阅读同学写的专题文章。 前言 CSS代码难维护众所皆知。 为一个元素设置样式的方式可以通过定义的class、定义的id、元素的标签名、元素的属性等选择器以及这些选择器的组合来实现; 作用于某个元素上的样式又可能来自单个样式规...

    keke 评论0 收藏0
  • CSS学习笔记(十四) 我们前端是怎么跟设计师沟通的

    摘要:前端期望中的设计能给予的除了之外,还有设计上游岗位传递下来的东西。份文件一份好的文件是分层清晰,设计规范的文件。有些页面设计师没有考虑到。地址如下原文链接我们前端是怎么跟设计师沟通的豪情博客园 1.交付 一般设计师给前端的只有psd,没有其它多余的东西,连基本的文档都懒得给。前端期望中的设计能给予的除了psd之外, 还有设计上游岗位传递下来的东西。 比如: 产品原型, 需求文档, 交...

    NusterCache 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<