《JavaScript框架设计》——第 1 章 种子模块 1.1命名空间

简介: IIFE是现代JavaScript框架最主要的基础设施,它像细胞膜一样包裹自身,防止变量污染。但我们总得在Windows里设置一个立足点,这个就是命名空间。基本上我们可以把命名空间等同于框架的名字,不过对于某些框架,它们是没有统一的命名空间,如Prototype.js , mootools。

本节书摘来自异步社区《JavaScript框架设计》一书中的第1章,第1.1节,作者:司徒正美著,更多章节内容可以访问云栖社区“异步社区”公众号查看

第 1 章 种子模块

种子模块也叫核心模块,是框架的最先执行的部分。即便像jQuery那样的单文件函数库,它的内部也分许多模块,必然有一些模块冲在前面立即执行,有一些模块只有用到才执行,也有一些模块可有可无,存在感比较弱,只在特定浏览器下才运行。

种子模块就是其中的急先锋,它里面的方法不一定要求个个神通广大,设计优良,但一定极具扩展性,常用,稳定。扩展性是指通过它们能将其他模块的方法包进来,让种子像大树一样成长;常用是指绝大多数模块都用到它们,防止做重复工作;稳定是指不能轻易在以后版本就给去掉,要信守承诺。

参照许多框架与库的实现,我认为种子模块应该包含如下功能:对象扩展,数组化,类型判定,简单的事件绑定与卸载,无冲突处理,模块加载与domReady。

1.1 命名空间

种子模块作为一个框架的最开始部分,除了负责辅建全局用的基础设施外,你有没有想到给读者一个震撼的开场呢?俗话说,好的开头是成功的一半。

时下“霸主”jQuery就有一个很好的开头——IIFE(立即调用函数表达式),一下子吸引住读者,让读者吃一颗定心丸——既然作者的水平如此高超,还怕什么啊,直接拿来用。

IIFE是现代JavaScript框架最主要的基础设施,它像细胞膜一样包裹自身,防止变量污染。但我们总得在Windows里设置一个立足点,这个就是命名空间。基本上我们可以把命名空间等同于框架的名字,不过对于某些框架,它们是没有统一的命名空间,如Prototype.js , mootools。它们就是不想让你感觉到框架的存在,它的意义深透到JavaScript、DOM、COM等整个执行环境的每个角落,对原生对象的原型进行扩展。由于道格拉斯(JSON作者)的极力反对,新兴的框架都在命名空间上构建了。

命名空间是干什么用呢?这里就不多说了。我们看怎么在JavaScript模拟命名空间。JavaScript一切基于对象,但只有复合类型的对象才符合这要求,比如function、regexp、object……不过最常用的还是object与function。我们往一个对象上添加一个属性,而这个属性又是一个对象,这个对象我们又可以为它添加一个对象,通过这种方法,我们就可以有条不紊地构建我们的框架。用户想调用某个方法,它就以XXX.YYY.ZZZ()的形式调用。

if (typeof(Ten) === "undefined") {
    Ten = {};
    Ten.Function = {/*略*/}
    Ten.Array = {/*略*/}
    Ten.Class = {/*略*/}
    Ten.JSONP = new Ten.Class(/*略*/)
    Ten.XHR = new Ten.Class(/*略*/)

纵观各大类库的实现,一开始基本都是定义一个全局变量作为命名空间,然后对它进行扩展,如Base2的Base、Ext的Ext、jQuery的jQuery、YUI的YUI、dojo的dojo、MochiKit的MochiKit等。从全局变量的污染程度来看,分为两大类。

Prototype、mootools与Base2归为一类。Prototype的哲学是对JavaScript原生对象进行扩展。早些年,Ptototype差点成为事实的标准,因此基本没有考虑到与其他库的共存问题。基于Prototype,也发展出诸如script.aculo.us、rico、Plotr、ProtoChart、Scripty 2等非常优秀的类库及一大堆收费插件,非jQuery那一大堆垃圾插件所能比拟的。而且,有点渊源的插件几乎都与Prototype有关,如著名的lightbox。mootools是Prototype的升级版,更加OO,全面复制其API。Base则是想修复IE的Bug,让IE拥有标准浏览器的API,因此也把所有原生对象污染一遍。

第二类是jQuery、YUI、EXT这些框架。YUI与EXT就是像上面给出的代码那样,以叠罗汉方式构建的。jQuery则另辟蹊径,它是以选择器为导向的,因此它的命名空间是一个函数,方便用户把CSS表达器字符串传进来,然后通过选择器引擎进行查找,最后返回一个jQuery实例。另外,像jQuery最初也是非常弱小的,它想让人家试用自己的框架,但也想像Prototype那样使用美元符号作为它的命名空间。因此它特意实现了多库共存机制,在$、jQuery与用户指定的新命名空间中任意切换。

jQuery的多库共存原理很简单,因此后来也成为许多小库的标配。首先把命名空间保存到一个临时变量中,注意这时这个对象并不是自己框架的东西,可能是Prototype.js等巨头的,然后再搞个noConflict放回去。

//jQuery1.2
var _jQuery = window.jQuery, _$ = window.$;//先把可能存在的同名变量保存起来
jQuery.extend({
    noConflict: function(deep) {
        window.$ = _$;//这时再放回去
        if (deep)
            window.jQuery = _jQuery;
        returnjQuery;
    }
})

但jQuery的noConflict只对单文件的类库框架有用,像EXT就不能复制了。因此把命名空间改名后,将EXT置为null,然后又通过动态加载方式引入新的JavaScript文件,该文件再以EXT调用,将会导致报错。

mass Framework对jQuery的多库共存进行改进,它与jQuery一样拥有两个命名空间,一个是美元符号的短命名空间,另一个是根据URL动态生成的长命名空间(jQuery就是jQuery!)。

namespace = DOC.URL.replace( /(#.+|\W)/g,'');
短的命名空间随便用户改名,长的命名空间则是加载新的模块时用的,虽然用户在模块中使用$做命名空间,但当JavaScript文件加载下来时,我们会对里面的内容再包一层,将$指向正确的对象,具体实现见define方法。

相关文章
|
1月前
|
缓存 JSON JavaScript
Node.js模块系统
10月更文挑战第4天
37 2
|
1月前
|
JavaScript 应用服务中间件 Apache
Node.js Web 模块
10月更文挑战第7天
29 0
|
1月前
|
JavaScript 网络协议
Node.js 工具模块
10月更文挑战第7天
20 0
|
3月前
|
JavaScript 数据可视化
JS如何优雅的实现模块自动滚动展示
【8月更文挑战第22天】JS如何优雅的实现模块自动滚动展示
34 1
JS如何优雅的实现模块自动滚动展示
|
1月前
|
JavaScript 前端开发 应用服务中间件
Node.js Web 模块
Node.js Web 模块
|
2月前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
这篇文章介绍了在Nest.js构建应用时,如何通过事件/发布-订阅模式使应用程序更健壮、灵活、易于扩展,并简化服务间通信。文章主要围绕@nestjs/event-emitter模块展开,这是一个基于eventemitter2库的社区模块,提供了事件发布/订阅功能,使得实现事件驱动架构变得简单。文章还介绍了如何使用该模块,包括安装依赖、初始化模块、注册EventEmitterModule、使用装饰器简化监听等。最后总结,集成@nestjs/event-emitter模块可以提升应用程序的事件驱动能力,构建出更为松耦合、易扩展且高度灵活的系统架构,是构建现代、响应迅速且具有高度解耦特性的Nest.
|
2月前
|
缓存 JavaScript 前端开发
JavaScript模块化开发:ES6模块与CommonJs的对比与应用
JavaScript模块化开发:ES6模块与CommonJs的对比与应用
32 2
|
3月前
|
算法 JavaScript 前端开发
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
271 1
|
3月前
|
存储 缓存 JSON
Node.js有哪些模块系统
【8月更文挑战第12天】Node.js有哪些模块系统
40 3
|
3月前
|
算法 JavaScript 前端开发
对称加密算法解析:DES、AES及其在`pycryptodome` 和 `crypto-js` 模块中的应用
对称加密算法解析:DES、AES及其在`pycryptodome` 和 `crypto-js` 模块中的应用
169 1