JavaScript 模块模式(三)
2014-05-04 19:15
239 查看
1、<Script>标签的位置
在JavaScript 高级编程中这样介绍-对于那些有许多JS代码页面而言,无疑导致浏览器在呈现页面时出现明显的延迟,而延迟期间浏览器有空白
为了避免这个问题:
建议 :在介绍</body>之前引入外部的JS文件。 针对引入少并且是重要的JS文件考虑考虑加入<head>中间(JS文件)</head>
对许多用户而言以上的还不足,我们可以采用以下的模式创造强大的,可扩展的结构。让我们使用MODULE模块,一个一个继续。
模块模式的一个限制是整个模块必须在一个文件里。任何人都了解长代码分割到不同文件的必要。还好,我们有很好的办法扩充模块。(在扩充文件)首先我们引入模块(从全局),给他添加属性,再输出他。下面是一个例子扩充模块:
我们再次使用var关键字以保持一致性,虽然其实没必要。代码执行后,模块获得一个新公开方法MODULE.anotherMethod。扩充文件没有影响模块的私有内部状态。
松耦合扩充
上面的例子需要我们首先创建模块,然后扩充它,这并不总是必要的。提升JavaScript应用性能最好的操作就是异步加载脚本。因而我们可以创建灵活多部分的模块,可以将他们无顺序加载,以松耦合扩充。每个文件应有如下的结构:
这个模式里,var语句是必须的,以标记引入时不存在会创建。这意味着你可以像LABjs一样同时加载所有模块文件而不被阻塞。
紧耦合扩充
虽然松耦合很不错,但模块上也有些限制。最重要的,你不能安全的覆写模块属性(因为没有加载顺序)。初始化时也无法使用其他文件定义的模块属性(但你可以在初始化后运行)。紧耦合扩充意味着一组加载顺序,但是允许覆写。下面是一个例子(扩充最初定义的MODULE):
我们覆写的MODULE.moduleMethod,但依旧保持着私有内部状态。
克隆和继承
这种方式也许最不灵活。他可以实现巧妙的组合,但是牺牲了灵活性。正如我写的,对象的属性或方法不是拷贝,而是一个对象的两个引用。修改一个会影响其他。这可能可以保持递归克隆对象的属性固定,但无法固定方法,除了带eval的方法。不过,我已经完整的包含了模块。(其实就是做了一次浅拷贝)。
跨文件私有状态
一个模块分割成几个文件有一个严重缺陷。每个文件都有自身的私有状态,且无权访问别的文件的私有状态。这可以修复的。下面是一个松耦合扩充的例子,不同扩充文件之间保持了私有状态:
view
source
print?
任何文件都可以在本地的变量_private中设置属性,他会对别的扩充立即生效(即初始化时所有扩充的私有状态都保存在_private变量,并被my._private输出)。模块完全加载了,应用调用MODULE._seal()方法阻止对私有属性的读取(干掉my._private输出)。如果此后模块又需要扩充,带有一个私有方法。加载扩充文件前调用MODULE._unseal()方法(恢复my._private,外部恢复操作权限)。加载后调用再seal()。
这个模式一直随我工作至今,我还没看到别的地方这样做的。我觉得这个模式很有用,值得写上。
子模块
最后的高级模式实际上最简单。有很多好方法创建子模块。和创建父模块是一样的:
虽然很简单,但我还是提一下。子模块有所有正常模块的功能,包括扩充和私有状态。
子模块。
这里我还没有涉及性能,不过我有个小建议:模块模式是性能增益的。他简化了许多,加快代码下载。松耦合可以无阻塞并行下载,等价于提高下载速度。可能初始化比别的方法慢一点,但值得权衡。只要全局正确的引入,运行性能不会有任何损失,可能还因为局部变量和更少的引用,加快子模块的加载。
最后,一个例子动态加载子模块到父模块(动态创建)中。这里就不用私有状态了,其实加上也很简单。这段代码允许整个复杂分成的代码核心及其子模块等平行加载完全。
来自:傅小黑
在JavaScript 高级编程中这样介绍-对于那些有许多JS代码页面而言,无疑导致浏览器在呈现页面时出现明显的延迟,而延迟期间浏览器有空白
为了避免这个问题:
建议 :在介绍</body>之前引入外部的JS文件。 针对引入少并且是重要的JS文件考虑考虑加入<head>中间(JS文件)</head>
高级模式
对许多用户而言以上的还不足,我们可以采用以下的模式创造强大的,可扩展的结构。让我们使用MODULE模块,一个一个继续。
扩充
模块模式的一个限制是整个模块必须在一个文件里。任何人都了解长代码分割到不同文件的必要。还好,我们有很好的办法扩充模块。(在扩充文件)首先我们引入模块(从全局),给他添加属性,再输出他。下面是一个例子扩充模块:1 | var MODULE = ( function (my) { |
2 | my.anotherMethod = function () { |
3 | // 此前的MODULE返回my对象作为全局输出,因此这个匿名函数的参数MODULE就是上面MODULE匿名函数里的my |
4 | }; |
5 |
6 | return my; |
7 | }(MODULE)); |
松耦合扩充
上面的例子需要我们首先创建模块,然后扩充它,这并不总是必要的。提升JavaScript应用性能最好的操作就是异步加载脚本。因而我们可以创建灵活多部分的模块,可以将他们无顺序加载,以松耦合扩充。每个文件应有如下的结构:
1 | var MODULE = ( function (my) { |
2 | // add capabilities... |
3 |
4 | return my; |
5 | }(MODULE || {})); |
紧耦合扩充
虽然松耦合很不错,但模块上也有些限制。最重要的,你不能安全的覆写模块属性(因为没有加载顺序)。初始化时也无法使用其他文件定义的模块属性(但你可以在初始化后运行)。紧耦合扩充意味着一组加载顺序,但是允许覆写。下面是一个例子(扩充最初定义的MODULE):
1 | var MODULE = ( function (my) { |
2 | var old_moduleMethod = my.moduleMethod; |
3 |
4 | my.moduleMethod = function () { |
5 | // method override, has access to old through old_moduleMethod... |
6 | }; |
7 |
8 | return my; |
9 | }(MODULE)); |
克隆和继承
01 | var MODULE_TWO = ( function (old) { |
02 | var my = {}, |
03 | key; |
04 |
05 | for (key in old) { |
06 | if (old.hasOwnProperty(key)) { |
07 | my[key] = old[key]; |
08 | } |
09 | } |
10 |
11 | var super_moduleMethod = old.moduleMethod; |
12 | my.moduleMethod = function () { |
13 | // override method on the clone, access to super through super_moduleMethod |
14 | }; |
15 |
16 | return my; |
17 | }(MODULE)); |
跨文件私有状态
一个模块分割成几个文件有一个严重缺陷。每个文件都有自身的私有状态,且无权访问别的文件的私有状态。这可以修复的。下面是一个松耦合扩充的例子,不同扩充文件之间保持了私有状态:
view
source
print?
01 | var MODULE = ( function (my) { |
02 | var _private = my._private = my._private || {}, |
03 | _seal = my._seal = my._seal || function () { |
04 | delete my._private; |
05 | delete my._seal; |
06 | delete my._unseal; |
07 | }, //模块加载后,调用以移除对_private的访问权限 |
08 | _unseal = my._unseal = my._unseal || function () { |
09 | my._private = _private; |
10 | my._seal = _seal; |
11 | my._unseal = _unseal; |
12 | }; //模块加载前,开启对_private的访问,以实现扩充部分对私有内容的操作 |
13 |
14 | // permanent access to _private, _seal, and _unseal |
15 |
16 | return my; |
17 | }(MODULE || {})); |
这个模式一直随我工作至今,我还没看到别的地方这样做的。我觉得这个模式很有用,值得写上。
子模块
最后的高级模式实际上最简单。有很多好方法创建子模块。和创建父模块是一样的:
1 | MODULE.sub = ( function () { |
2 | var my = {}; |
3 | // 就是多一级命名空间 |
4 |
5 | return my; |
6 | }()); |
子模块。
这里我还没有涉及性能,不过我有个小建议:模块模式是性能增益的。他简化了许多,加快代码下载。松耦合可以无阻塞并行下载,等价于提高下载速度。可能初始化比别的方法慢一点,但值得权衡。只要全局正确的引入,运行性能不会有任何损失,可能还因为局部变量和更少的引用,加快子模块的加载。
最后,一个例子动态加载子模块到父模块(动态创建)中。这里就不用私有状态了,其实加上也很简单。这段代码允许整个复杂分成的代码核心及其子模块等平行加载完全。
01 | var UTIL = ( function (parent, $) { |
02 | var my = parent.ajax = parent.ajax || {}; |
03 |
04 | my.get = function (url, params, callback) { |
05 | // ok, so I'm cheating a bit :) |
06 | return $.getJSON(url, params, callback); |
07 | }; |
08 |
09 | // etc... |
10 |
11 | return parent; |
12 | }(UTIL || {}, jQuery)); |
相关文章推荐
- javascript_静态私有变量,模块模式,增强模块模式
- 深入理解 JavaScript 模块模式
- javascript的模块模式
- 深入理解JavaScript中的块级作用域、私有变量与模块模式
- 深入理解 JavaScript 模块模式
- JavaScript模块模式实例详解
- Javascript 模块模式
- 深入理解JavaScript 模块模式
- javascript(模块模式)
- JavaScript设计模式-单例模式、模块模式
- 理解JavaScript模块模式
- JavaScript编程模式:模块的力量
- Javascript中的单例和模块模式
- Javascript 设计模式 -- Revealing Module(揭示模块)模式
- JavaScript 匿名函数、模块模式、闭包、命名空间、创建构造器(类)、继承
- 深入理解JavaScript 模块模式
- 深入理解JavaScript 模块模式
- 理解JavaScript模块模式