领先一步
VMware 提供培训和认证,助您加速进步。
了解更多大约十年前,Adrian Colyer写了一篇令人难忘的博客文章,对面向切面编程(AOP)进行了最佳解释:清晰简洁的风格,准确的内容,没有浮华的辞藻。如果你看过本系列早期的两篇文章,你可能已经注意到我们在Sagan应用程序的客户端模块中的一些架构选择,包括使用JavaScript模块。
在这篇文章中,我想以Adrian文章的风格带你了解JavaScript模块的基础知识:清晰、简单、准确、没有浮华的辞藻!
如果你像我一样有Java背景,一些JavaScript语言特性可能看起来有点奇怪
简单的Web应用程序通常看起来像这样
<html>
<head>
<!-- scripts are loaded **sequentially** -->
<script src="jquery.js"></script>
<script src="widget.js"></script>
<!-- all objects are in the global namespace,
no way to isolate the code completely! -->
<script>
window.$; // this is jquery
</script>
</head>
</html>
开发人员通常会尝试重用功能块并管理它们之间的依赖关系。在前面的情况下,这很难实现:你必须按正确的顺序声明脚本并避免名称冲突,而没有任何关于依赖项的元数据。随着应用程序的增长,这项任务会变成一场噩梦:想象一下,在没有包或依赖管理基础设施的情况下管理你的Java应用程序!
幸运的是,JS社区充分意识到模块化的需求,在过去几年中,出现了几种广泛采用的解决这个问题的方法
AMD (Asynchronous Module Definition) 是其中之一
// defining a module that depends on "graphmodule",
// injected in the function definition as an argument
define(["graphmodule"],
function (graph) {
// this module exports a "draw" function
return function draw(data) {
return graph.piechart(data);
}
}
);
AMD格式常用于浏览器应用程序,因为
CommonJS 是另一种创作格式,常用于服务器端的Node.js应用程序,但也用于浏览器应用程序。
/**
* Our module's dependencies and API
**/
// we fetch the graph module as a dependency
var graph = require('graphmodule');
// we decorate the `exports` variable to export our function
exports.draw = drawFunc;
/**
* API implementation
**/
function drawFunc(data) {
return graph.piechart(data);
}
你可能发现了与AMD的一些区别
define中JavaScript的下一个版本(技术上称为ECMAScript 6)将标准化JavaScript模块化,尽管使用的语法与我们上面看到的AMD或CommonJS格式略有不同。此外,EcmaScript 6将解决该领域的许多问题,但也将提供语法糖来定义类似OO的类。
无论你在哪里使用JavaScript,无论是客户端还是服务器,都请考虑采用模块化方法——原因与我们在Java中采用模块化的原因完全相同。熟练掌握JS模块技术需要一点学习曲线,但结果非常值得。
如果你是JavaScript模块化的新手,我建议你查看“编写CommonJS模块”教程以及我们在Sagan中使用的模块加载器:curl。一旦你熟悉了,请查看我们在Sagan应用程序中的模块定义。