0

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

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

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

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

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

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

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

我写了一个小脚本,准确地演示了我遇到的问题。它是在这个 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));

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

4

1 回答 1

0

我不确定这是一种合理的做法还是混乱,但我创建了一个在 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));
于 2013-04-18T19:43:35.710 回答