js发展初期暴露了其缺陷:缺少模块,后来提出了commonJS规范来规范其模块的规范。做为JavaScript新手,发现对于其JavaScript的模块机制,不是很理解。我查阅了一些资料整理了JavaScript CommonJS的原理和机制。css
这类项目不能使用CommonJS的模块规范,这是我起初所犯的错误。在没有es6被大多数浏览器支持的时候,js文件充斥着var和function,由此引来了命名冲突和污染,使得JavaScript代码很复杂。es6的class概念出现有效规范了JavaScript的模块化规范。因为这类项目只能经过script标签引入,咱们在这里讲一下script标签的相关知识。
每当浏览器解析到<script>标签(不管内嵌仍是外链)时,浏览器会优先下载、解析并执行该标签中的javaScript代码,而阻塞了其后全部页面内容的下载和渲染。根据上述对<script>标签特性的描述,咱们知道,在该示例中,当浏览器解析到<script>标签时,浏览器会中止解析其后的内容,而优先下载脚本文件,并执行其中的代码,这意味着,其后的test.css样式文件和<body>标签都没法被加载,因为<body>标签没法被加载,那么页面天然就没法渲染了。所以传统作法是
假定point.js文件:html
//定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } }
则在index.js中引入point.js,这须要在index.html中body的尾部java
<script src="point.js"></script> <script src="index.js"></script>
这样就能够在index.js使用point类了。
总结下来:es6
js类库必须在header中引入,保证对以后script引入的js文件的支持,毕竟script标签的执行顺序是顺序执行,script标签引入顺序和实际引入顺序相同。后端
自定义的script标签引入的js文件,要放在body的尾部,保证DOM元素渲染结束。浏览器
每一个js文件尽可能是es6 class对象,避免做用域和命名域的冲突。服务器
模块引用的实例以下:require方法模块化
const math = require("math");
模块的定义:
上下文提供了exports对象用于导出当前模块方法和变量,而且它是惟一的导出出口。在模块中,还存在一个module对象,他表明模块自身,exports是module对象的属性。导出方式:工具
// math.js exports.add = function () { }; module.exports.add = function () { };
ES6模块不是对象,而是经过export命令显式指定输出的代码,输入时也采用静态命令的形式。
因为ES6模块是编译时加载,使得静态分析成为可能。有了它,就能进一步拓宽JavaScript的语法,好比引入宏(macro)和类型检验(type system)这些只能靠静态分析实现的功能。 ui
除了静态加载带来的各类好处,ES6模块还有如下好处:
再也不须要UMD模块格式了,未来服务器和浏览器都会支持ES6模块格式。目前,经过各类工具库,其实已经作到了这一点。
未来浏览器的新API就能用模块格式提供,再也不必要作成全局变量或者navigator对象的属性。
再也不须要对象做为命名空间(好比Math对象),将来这些功能能够经过模块提供。
浏览器使用ES6模块的语法以下:
导出对象和变量:
variables.js
var firstName = 'XXX'; var lastName = 'YYY'; export {firstName, lastName};
Point.js
// 导出类对象 export default class Point extends circle { }
引入module
import Point from "Point";
加载机制详见:es6 module
引用资料:
高静:js的并行加载与顺序执行