【问题标题】:Structuring a JavaScript app using a modular approach使用模块化方法构建 JavaScript 应用程序
【发布时间】:2013-04-18 18:16:38
【问题描述】:

我正在尝试编写一个足够大的 JavaScript 应用程序,模块化可能是一个好主意。我正在使用著名的继承函数来使对象能够从具有参数的构造函数继承。问题是我收到一个错误,即传递给继承函数的父级未定义。这是因为,调用继承时尚未定义父构造函数。

我想出了一些丑陋的解决方案来解决这个问题:

  1. 在其父构造函数 (yuk) 之后声明所有子构造函数。

  2. 将所有原型分配绑定到一个自定义事件,并使用有序回调链确保所有原型按顺序分配(也许有潜力)。

  3. 将所有原型分配从其构造函数所在的代码区域中移出,并将它们合并(和放逐)到一些“分配原型”函数(是第一项的两倍,不是吗?)。

底线是我不希望我的构造函数、方法和对象在代码中的写入顺序基于代码的加载/解释顺序。我希望我的代码易于扩展并将相关代码组合在一起以便易于理解(即原型分配不应该靠近构造函数声明/定义吗?)。

我将模块放置在单独的文件中,并在将它们发送到浏览器之前使用 PHP 脚本将它们全部附加在一起。 PHP 脚本只确保首先包含声明命名空间的文件,然后将 js 文件与 glob 连接起来。

我编写了一个小脚本来准确演示我遇到的问题。它是is live at this url。屏幕是白色的,因为没有 html — 我这里使用控制台进行分析。

/*global console, jQuery, $, myNS: true*/
/*jslint browser: true*/

/*
 * This file is deliberately set as the first file in the php glob.
 */
var myNS = (function (myNS, $, window, undefined) {
    "use strict";

    /*
     * @param {object} coords -- e.g. {x: 3, y: 26}
     */
    myNS = function (coords) {
        return new myNS.CartesianLoc(coords);
    };

    // static methods
    myNS.inherit = function (parent) {
        function F() {}
        F.prototype = parent.prototype;
        return new F();
    };
    myNS.getWinCenter = function () {
        return {
            x : $(window).width() / 2,
            y : $(window).height() / 2
        };
    };

    // prototype
    myNS.prototype = {
        log: function () {
            if (window.console) {
                console.log(this);
            }
        }
    };

    return myNS;
}(myNS, jQuery, window));



/*
 * This is another file.
 */
(function (myNS, $, window, undefined) {
    "use strict";
    /*
     *  CartesianLoc constructor
     *
     *  @param {object} coords -- given in a conceptual
     *  Cartesian space where the origin (0,0) is
     *  the middle of whatever screen
     */
    function CartesianLoc(coords) {
        myNS.Loc.call(this, coords);
    }
    CartesianLoc.prototype = myNS.inherit(myNS.Loc);
    CartesianLoc.prototype.constructor = CartesianLoc;

    CartesianLoc.prototype.getWinCoords = function () {
        return {
            x: myNS.getWinCenter().x + this.x,
            y: myNS.getWinCenter().y + this.y
        };
    };

    myNS.CartesianLoc = CartesianLoc;
}(myNS, jQuery, window));



/*
 * This is another file.
 */
(function (myNS, $, window, undefined) {
    "use strict";
    // Location constructor
    function Loc(coords) {
        this.x = coords.x;
        this.y = coords.y;
    }
    Loc.prototype = myNS.inherit(myNS);
    Loc.prototype.constructor = Loc;

    Loc.prototype.translate = function (coords) {
        this.loc.x += coords.x;
        this.loc.y += coords.y;
        return this;
    };

    myNS.Loc = Loc;
}(myNS, jQuery, window));



/*
 * Application js file
 *
 */

(function (myNS, $, window, undefined) {
    "use strict";

    $(document).ready(function (event) {
        if (console) {
            console.log("%o", new myNS({x: 100, y: -45}));
        }
    });

}(myNS, jQuery, window));

感谢您能给我的任何帮助或想法!
克里斯

【问题讨论】:

    标签: javascript oop interpreter modularity prototypal-inheritance


    【解决方案1】:

    我不确定这是一种合理的做法还是混乱,但我创建了一个在 document.ready 上触发的自定义事件,并将所有分配原型的代码放在该事件的回调中。我知道我正在添加一个在另一个事件被触发时触发的事件(这在它的表面上似乎毫无意义),但我希望自定义事件成为被监听的事件,以防我想改变它稍后触发的方式。

    /*global console, jQuery, $, myNS: true*/
    /*jslint browser: true*/
    
    /*
     * This file is deliberately set as the first file in the php glob.
     */
    var myNS = (function (myNS, $, window, undefined) {
        "use strict";
    
        /*
         * @param {object} coords -- e.g. {x: 3, y: 26}
         */
        myNS = function (coords) {
            return new myNS.CartesianLoc(coords);
        };
    
        // Triggered after all constructors have been defined
        $(document).ready(function (event) {
            $(document).trigger("myNS");
        });
    
        // static methods
        myNS.inherit = function (parent) {
            function F() {}
            F.prototype = parent.prototype;
            return new F();
        };
        myNS.getWinCenter = function () {
            return {
                x : $(window).width() / 2,
                y : $(window).height() / 2
            };
        };
    
        // prototype
        myNS.prototype = {
            log: function () {
                if (window.console) {
                    console.log(this);
                }
            }
        };
    
        return myNS;
    }(myNS, jQuery, window));
    
    
    
    /*
     * This is another file.
     */
    (function (myNS, $, window, undefined) {
        "use strict";
        /*
         *  CartesianLoc constructor
         *
         *  @param {object} coords -- given in a conceptual
         *  Cartesian space where the origin (0,0) is
         *  the middle of whatever screen
         */
        function CartesianLoc(coords) {
            myNS.Loc.call(this, coords);
        }
        $(document).on('myNS', function (event) {
            CartesianLoc.prototype = myNS.inherit(myNS.Loc);
            CartesianLoc.prototype.constructor = CartesianLoc;
    
            CartesianLoc.prototype.getWinCoords = function () {
                return {
                    x: myNS.getWinCenter().x + this.x,
                    y: myNS.getWinCenter().y + this.y
                };
            };
        });
        myNS.CartesianLoc = CartesianLoc;
    }(myNS, jQuery, window));
    
    
    
    /*
     * This is another file.
     */
    (function (myNS, $, window, undefined) {
        "use strict";
        // Location constructor
        function Loc(coords) {
            this.x = coords.x;
            this.y = coords.y;
        }
        $(document).on('myNS', function (event) {
            Loc.prototype = myNS.inherit(myNS);
            Loc.prototype.constructor = Loc;
    
            Loc.prototype.translate = function (coords) {
                this.loc.x += coords.x;
                this.loc.y += coords.y;
                return this;
            };
        });
        myNS.Loc = Loc;
    }(myNS, jQuery, window));
    
    
    
    /*
     * Application js file
     *
     */
    
    (function (myNS, $, window, undefined) {
        "use strict";
    
        $(document).ready(function (event) {
            if (console) {
                console.log("%o", new myNS({x: 100, y: -45}));
            }
        });
    
    }(myNS, jQuery, window));
    

    【讨论】:

      猜你喜欢
      • 2014-08-11
      • 2018-09-28
      • 2019-10-13
      • 2020-02-27
      • 2014-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      相关资源
      最近更新 更多