Common JS 模块化

JavaScript010

Common JS 模块化,第1张

首先我们要明白一个前提,CommonJS模块规范和ES6模块规范完全是两种不同的概念。

我们知道在浏览器环境中,使用var声明一个全局变量会把该变量挂载到window对象上去,所以我们才可以访问到window.a

那如果是在node环境中呢?

如果我们在一个js文件中直接打印window是找不到这个顶层对象的,因为node环境下的顶层对象是global,

那我们声明的全局变量会不会像window对象一样挂载到global对象上呢?下面我们来试一下。

我们要想把变量a挂载到global对象上就必须要这样做

但是为什么会是undefined呢?

这就涉及到了模块化,在node环境中会存CommonJS模块化,它会把当前的文件当成模块的方式加载,那怎么理解以模块的方式加载呢?

我们可以简单的认为,每一个模块就是一个函数,模块中的内容就相当于是函数中的内容。

我们再想另一个问题,既然模块是一个函数,函数里的this指向是什么呢?

我们知道函数中的this是指向调用它的对象的,然而每个模块又是一个函数,node环境中的this又不能指向window,那会是指向谁呢?经过试验,发现node环境下的this指向的是一个空对象,这是因为node环境下的this指向的其实就是该模块导出的对象,默认是一个空对象

那我们如何让this指向全局对象global呢?很简单,把内容放到一个自执行函数里面就可以了,因为自执行函数里面的this永远指向全局对象

函数都会有arguments参数列表,而模块作为一个函数它的arguments又是什么呢?

module 和 exports 是Node.js给每个js文件内置的两个对象

在 a.js 中用 exports 或 module.exports 导出的对象,可以再另一个文件中通过该 require() 引用。

实际上,这两个对象指向同一块内存,也就是说他们两个是等价的(不去改变他们指向的内存地址)

require 引入的对象本质上是 module.exports .当 module.exports 和 exports 指向的不是同一块内存, exports 导出的内容就会失效。

我们在开发及接触新技术的时候,总会接触到该技术以何种规范编写,为了更加系统了解这些规范,本文总结了AMD,CMD,CommonJs,UMD,ESM几种规范,供大家学习了解。

AMD 是 RequireJS 在推⼴过程中对 模块定义的规范化 产出,它是⼀个概念,RequireJS是对这个概念的实现,就好⽐JavaScript语⾔是对ECMAScript规范的实现。AMD是⼀个组织,RequireJS是在这个组织下⾃定义的⼀套脚本语⾔

RequireJS:是⼀个AMD框架,可以异步加载JS⽂件,按照模块加载⽅法,通过define()函数定义。第⼀个参数是⼀个数组,⾥⾯定义⼀些需要依赖的包,第⼆个参数是⼀个回调函数,通过变量来引⽤模块⾥⾯的⽅法,最后通过return来输出()。

是⼀个 依赖前置 、 异步定义 的AMD框架(在参数⾥⾯引⼊js⽂件),在定义的同时如果需要⽤到别的模块,在最前⾯定义好即在参数数组⾥⾯进⾏引⼊,在回调⾥⾯加载

AMD 定义了一套 JavaScript 模块依赖异步加载标准,来解决同步加载的问题。模块通过 define 函数定义在闭包中,格式如下:

define(id?: String, dependencies?: String[], factory: Function|Object)

一些栗子:

注意:在 webpack 中,模块名只有局部作用域,在 Require.js 中模块名是全局作用域,可以在全局引用。

定义一个没有 id 值的匿名模块,通常作为应用的启动函数:

依赖多个模块的定义:

模块输出:

在模块定义内部引用依赖:

SeaJS 在推⼴过程中对模块定义的规范化产出,是⼀个同步模块定义,是SeaJS的⼀个标准,SeaJS是CMD概念的⼀个实现,SeaJS是淘宝团队提供的⼀个模块开发的js框架.

通过define()定义, 没有依赖前置 ,通过require加载模块,CMD是 依赖就近 ,在什么地⽅使⽤到模块就在什么地⽅require该模块,即⽤即返,这是⼀个 同步 的概念

在前端浏览器⾥⾯并不⽀持module.exports,CommonJS 是以在浏览器环境之外构建 JavaScript 生态系统为目标而产生的项目,比如在服务器和桌面环境中。

Nodejs端是使⽤CommonJS规范的,前端浏览器⼀般使⽤AMD、CMD、ES6等定义模块化开发的。输出⽅式有2种:默认输出module export 和带有名字的输出exports.area

CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块它自身的命名空间中执行。该规范的主要内容是,模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。

兼容AMD和commonJS规范的同时,还兼容全局引⽤的⽅式

1、什么是模块呢?我们可以简单的把它看成一个实现单独功能的文件。比如在前端JS中的jQuery.js,在node.js里,我们把它就看成一个模块的概念就行。 在前端的JS在使用它之前,是用 先要引入此文件。在node.js里,则需要require来引入.

我们新建一个require文件,来引入一下原来写好的sum.js require("./sum")我们发现sum.js文件就自动的运行了。 如果我们想把sum.js里的值获得到、或运行sum.js里定义的一个方法怎么办呢?

大家要注意,定义在模块里的方法,一定要用exports来暴露给调用它的文件,否则无法调用。在前端JS里,被引入的文件里定义的全局变量,在当前文件里是可以使用的,但node.js里不可以。这一点不同于前端的JS

每一个模块都相当于一个私有的作用域。这个模块里定义的变量,调用它的文件是访问不到了,除非用exports来暴露出来.

2、模块的需要返反的值,通过赋给exports的某个属性

3、包的概念:包含一个或多模块的(也就是JS文件的)文件夹(我们先简单的理为包就是一个实现完整功能的目录,其实它的意义远不止这些,先这样上手)

4、什么叫依赖?1、通俗的说就是包里各个文件之前的关系等。比如说谁是主文件(入口文件)2、包与包之间的引用关系。

在node.js里,是有模块和包这两个概念的,一个单独功能的文件,就是一个模块,可能一个复杂的功能,由多个模块组成,我们则把这多个模块,其实也就是文件,组织在一个文件夹里,然后用一个叫package.json的文本文件,来规定这些JS文件之间的关系(这个关系在node.js里叫依赖,就是包里的文件的组织关,一个包里,就是一个文件夹里,最其码要有一个主文件,可能这个主文件还要导入其它的JS文件才能运行,那package.json里,要把这个关系描述清楚)

5、包是模块化JS必须的。

我们可以在node.js项目中直使用别人写好的功能,就是使用别人写的包。也可以自己写一个包,发布到互联网上供大家使用。