CommonJS与ES6模块化的具体使用方式

JavaScript028

CommonJS与ES6模块化的具体使用方式,第1张

所以:只需要将需要暴露给外部的变量或者方法 设置为exports的属性 就行,

可以把exports看做一个全局对象,把所有暴露出来的函数和变量都存放在里面

1.先写个6.js文件

CommonJS规范规定,每个模块内部,module变量代表当前模板,这个变量是一个对象,他的 exports 属性(相当于 module.exports )是对外的接口。 这里详情请看我的另一篇文章: module、exports 和 require的关系

加载某个模块,其实是加载该模块的module.exports属性。require方法用于加载模块

ES6模块化的使用方法:(注!因为CommonJS类库众多,以及 CommonJS 和 ES6 之间的差异,所以无法直接兼容es6。)

直接/按需导出:可使用多个 用变量/常量的方式

导入:需要用按需导入 {解构} 的方式获取

默认导出:只能使用一个 (default属性只有es6才有)可以用引入对象定义多个属性,但这样在引入后调用的时候,更麻烦。

导入:优点:可以直接使用文件做接收参数且不用结构。

重命名export和import

如果导入的多个文件中,变量名字相同,即会产生命名冲突的问题,为了解决该问题,ES6为提供了重命名的方法,当你在导入名称时可以这样做:

如果想看CommonJS与ES6模块化的原理 可以去看我另一篇文章

[秦圆圆]大佬写的 require和import的区别

[大孩子气]大佬写的 require/exports、import/export 的区别

[七分sunshine!]大佬写的# 前端模块化工具 requireJs的使用

Base做的事情包括:

给模块增加自定义事件支持

给模块增加set和get方法

设置一些默认执行的方法,比如_init

提供模块的构建功能

提供模块的扩展功能

自定义事件

自定义事件模式是非常实用的,自定义事件用比较专业的词语描述的话,可以称为观察者模式,这种模式背后的主要动机就是促进形成松散耦合。在这种模式中,并不是一个对象调用另外一个对象的方法,而是一个对象订阅另外一个对象的特定活动并在状态改变后等到通知。这意味着我们在做一些事情的时候,不需要关注另外事情的进展,让另外一件事情来监听进展,然后做出对应的处理即可。这样的话,不同的事情之间就不会存在太多的关联,从而降低开发的复杂度。

set和get方法

为了保护和更好地稳定模块的执行,需要对模块参数的修改做一些限制和处理。所以需要提供set和get方法(现在的Base还没有在get的时候做一些处理),set可以用于在设置模块属性的时候,做一些过滤和处理,保证设置值的正确性,而且更重要的是,可以在set中触发一个属性修改的事件,从而可以做到修改属性的时候触发一些其他的变化。get则可以用于在访问属性的时候,对返回的属性做一些处理。对于模块内部而言,还需要有一个私有的_set和_get属性,从而可以和外部对模块的访问进行区分。

一些默认执行的方法

默认执行的方法会在两个地方存放,一个是在构造函数中,还有一个是在模块原型上的initliazer方法中。构造函数内主要处理模块间和实例的关系,这些处理是会继承到子模块中的,而在initliazer中主要处理模块真正相关的要执行的一些实例化方法,这样能保证模块在被继承的时候,自有的一些初始化方法不会被继承下去。而initliazer方法是由_init方法调用的,_init方法是模块实例化的时候必定会执行的方法,而initliazer是一个可选的初始化方法。

模块的构建和扩展

Base核心部分就是对模块的构建和扩展。先上代码

Base._build = function (moduleName, superModule, prototypeMethod, attrMember, staticMember, curConstructor) {

//使用prototype方式继承

var Module = function () {

Module.superclass.constructor.apply(this, arguments)

//保存对实例的引用

Module._instances[$.zid(this)] = this

}

if(curConstructor){

Module = curConstructor

}

//如果给定了构造函数,就在给定的构造函数上进行扩展,否则试用默认的构造函数

return Base._handlerClass(moduleName, Module, superModule, prototypeMethod, attrMember, staticMember)

}

Base._handlerClass = function (moduleName, module, superModule, prototypeMethod, attrMember, staticMember) {

var tempFn = function () {

},

o = {

name:moduleName,

value:module

}

//创建对象来保存实例的引用

module._instances = {}

//模块NAME

if (moduleName) {

module.NAME = moduleName

}

/*Module.toString = function(){

return moduleName

}*/

//如果没有传入要继承的对象,则默认为Base

superModule = superModule || Base

attrMember = attrMember || {}

staticMember = staticMember || {}

prototypeMethod = prototypeMethod || {}

//挂载ATTRS属性

//如果是继承于另外一个模块,则需要将ATTRS进行合并处理

if (superModule.NAME !== BASE) {

$.extend(attrMember, superModule.ATTRS)

}

//@20120830修复构造函数自带ATTRS时对应的处理方式

module.ATTRS = module.ATTRS || {}

$.extend(module.ATTRS, attrMember)

//挂在静态属性

$.extend(module, staticMember)

//拷贝一份prototype,防止构造函数直接执行

tempFn.prototype = superModule.prototype

module.prototype = new tempFn()

//把方法添加到Module的原型上

$.extend(module.prototype, prototypeMethod)

//修改构造器,防止回溯失败

module.prototype.constructor = module

//保存对超类的引用

module.superclass = superModule.prototype

if (superModule.prototype.constructor == Object.prototype.constructor) {

superModule.prototype.constructor = superModule

}

//保存生成的对象

Base.classList.push(o)

return module

}

代码细节都有注释,就不多说,主要还是把具体做的事情描述下

确定构造函数。

创建一个空对象来保存实例的引用。

确定模块名。

确定是否继承于其他模块。

拷贝参数的策略(ATTRS)和静态成员

创建原型并拷贝实例成员(原型上的成员)

修复创建原型后构造器指向不对的问题

创建对超类的引用,从而可以手动访问超类

保存生存的对象引用

返回改造完成后的模块

注:以上构造模块的思路主要参考自YUI3的Base模块。

在下一篇中,将用这个Base模块来构建一个tab组件

如今backbone、emberjs、spinejs、batmanjs

等MVC框架侵袭而来。CommonJS、AMD、NodeJS、RequireJS、SeaJS、curljs等模块化的JavaScript扑面而

来。web前端已经演变成大前端,web前端的发展速度之快。

1)我们来看看什么是模块化?

模块化是一种将系统分离成独立功能部分的方法,可将系统分割成独立的功能部分,严格定义模块接口、模块间具有透明性。javascript中的模块在一些C、PHP、java中比较常见:

c中使用include 包含.h文件php中使用require_once包含.php文件

java使用import导入包

此中都有模块化的思想。

2)模块化的优缺点:

a>优点:

可维护性

1.灵活架构,焦点分离

2.方便模块间组合、分解

3.方便单个模块功能调试、升级

4.多人协作互不干扰

可测试性

1.可分单元测试

b>缺点:

性能损耗

1.系统分层,调用链会很长

2.模块间通信,模块间发送消息会很耗性能

3)最近的项目中也有用到模块化,

使用的是seajs,但是当引用到jquery,jquery easyui/或者jquery

UI组件时,有可能会用到很多jquery插件,那这样要是实现一个很复杂的交互时,模块间的依赖会很多,使用define()方法引入模块会很多,不知

有么有什么好的方法?

4)附:

内聚度

内聚度指模块内部实现,它是信息隐藏和局部化概念的自然扩展,它标志着一个模块内部各成分彼此结合的紧密程度。好处也很明显,当把相关的任务分组后去阅读就容易多了。 设计时应该尽可能的提高模块内聚度,从而获得较高的模块独立性。

耦合度

耦合度则是指模块之间的关联程度的度量。耦合度取决于模块之间接口的复杂性,进入或调用模块的位置等。与内聚度相反,在设计时应尽量追求松散耦合的系统。