@@ -633,4 +633,100 @@ MYAPP.utilities.module = (function (app, global) {
633
633
634
634
现在我们来看一下如何实现` Sandbox() ` 构造函数和它的模块来支持上面讲到的所有功能。
635
635
636
+ ### 添加模块
637
+
638
+ 在动手实现构造函数之前,我们来看一下如何添加模块。
639
+
640
+ ` Sandbox() ` 构造函数也是一个对象,所以可以给它添加一个` modules ` 静态属性。这个属性也是一个包含名值(key-value)对的对象,其中key是模块的名字,value是模块的功能实现。
641
+
642
+ Sandbox.modules = {};
643
+
644
+ Sandbox.modules.dom = function (box) {
645
+ box.getElement = function () {};
646
+ box.getStyle = function () {};
647
+ box.foo = "bar";
648
+ };
649
+
650
+ Sandbox.modules.event = function (box) {
651
+ // access to the Sandbox prototype if needed:
652
+ // box.constructor.prototype.m = "mmm";
653
+ box.attachEvent = function () {};
654
+ box.dettachEvent = function () {};
655
+ };
656
+
657
+ Sandbox.modules.ajax = function (box) {
658
+ box.makeRequest = function () {};
659
+ box.getResponse = function () {};
660
+ };
661
+
662
+ 在这个例子中我们添加了` dom ` 、` event ` 和` ajax ` 模块,这些都是在每个类库或者复杂的web应用中很常见的代码片段。
663
+
664
+ 实现每个模块功能的函数接受一个实例` box ` 作为参数,并给这个实例添加属性和方法。
665
+
666
+ ### 实现构造函数
667
+
668
+ 最后,我们来实现` Sandbox() ` 构造函数(你可能会很自然地想将这类构造函数命名为对你的类库或者应用有意义的名字):
669
+
670
+ function Sandbox() {
671
+ // turning arguments into an array
672
+ var args = Array.prototype.slice.call(arguments),
673
+ // the last argument is the callback
674
+ callback = args.pop(),
675
+ // modules can be passed as an array or as individual parameters
676
+ modules = (args[0] && typeof args[0] === "string") ? args : args[0], i;
677
+
678
+ // make sure the function is called
679
+ // as a constructor
680
+ if (!(this instanceof Sandbox)) {
681
+ return new Sandbox(modules, callback);
682
+ }
683
+
684
+ // add properties to `this` as needed:
685
+ this.a = 1;
686
+ this.b = 2;
687
+
688
+ // now add modules to the core `this` object
689
+ // no modules or "*" both mean "use all modules"
690
+ if (!modules || modules === '*') {
691
+ modules = [];
692
+ for (i in Sandbox.modules) {
693
+ if (Sandbox.modules.hasOwnProperty(i)) {
694
+ modules.push(i);
695
+ }
696
+ }
697
+ }
698
+
699
+ // initialize the required modules
700
+ for (i = 0; i < modules.length; i += 1) {
701
+ Sandbox.modules[modules[i]](this);
702
+ }
703
+
704
+ // call the callback
705
+ callback(this);
706
+ }
707
+
708
+ // any prototype properties as needed
709
+ Sandbox.prototype = {
710
+ name: "My Application",
711
+ version: "1.0",
712
+ getName: function () {
713
+ return this.name;
714
+ }
715
+ };
716
+
717
+ 这个实现中的一些关键点:
718
+
719
+ - 有一个检查` this ` 是否是` Sandbox ` 实现的过程,如果不是(也就是调用` Sandbox() ` 时没有加` new ` ),我们将这个函数作为构造函数再调用一次。
720
+ - 你可以在构造函数中给` this ` 添加属性,也可以给构造函数的原型添加属性。
721
+ - 被依赖的模块可以以数组的形式传递,也可以作为单独的参数传递,甚至以` * ` 通配符(或者省略)来表示加载所有可用的模块。值得注意的是,我们在这个示例实现中并没有考虑从外部文件中加载模块,但明显这是一个值得考虑的事情。比如YUI3就支持这种情况,你可以只加载最基本的模块(作为“种子”),其余需要的任何模块都通过将模块名和文件名对应的方式从外部文件中加载。
722
+ - 当我们知道依赖的模块之后就初始化它们,也就是调用实现每个模块的函数。
723
+ - 构造函数的最后一个参数是回调函数。这个回调函数会在最后使用新创建的实例来调用。事实上这个回调函数就是用户的沙箱,它被传入一个` box ` 对象,这个对象包含了所有依赖的功能。
724
+
725
+
726
+
727
+
728
+
729
+
730
+
731
+
636
732
0 commit comments