使用模块拆分大型课程

时间:2014-08-19 02:12:58

标签: javascript node.js browserify commonjs

我正在尝试构建我的第一个(浏览器)库,并选择使用节点样式的commonjs模块+ browserify来组织我的代码。我已经构建了它,所以每个模块包含1个类,这个类很好,直到一些类开始变得非常庞大。

所以我想说我有一个像

这样的课程
module.exports = MyClass;

function MyClass() {
  //initializing stuff

  this.publiceMethod= function publicMethod() {
    //do stuff
  };

  var privateMethod = function privateMethod() {
    //do stuff
  };
}

MyClass.prototype.notSureMethod = function notSureMethod() {
  //err... static method?
}

问题在于我有一些大量方法,使用各种方法来声明它们(this.methodvar methodthis.prototype.method)。我想知道的是,是否有一种相对简单的方法来创建另一个模块并将它们作为类定义的一部分加入MyClass以提高可读性。

我正在寻找的理想行为就像一个模块,它是一个自动执行的函数,与它的调用范围相同(如果可能,包括私有变量/方法)。

我现在只学习了几个星期的JS,所以如果我是愚蠢的话,请继续关注我。在此先感谢:)

- 编辑 -

盲目地玩弄它,我已经找到了如何用原型和公共方法做我正在寻找的东西。

//Underneath MyClass definition
require('./prototype-methods')(MyClass);
require('./public-methods')(MyClass);

然后在其他文件中的要点是:

module.exports = function(MyClass) {
  MyClass.prototype.method = . . . .

  MyClass.method = . . . .
}

这让我想知道是否有办法用私有方法做类似的事情。有什么想法吗?

--- --- EDIT2

  

你到底是什么用例?你能举一个例子说明你的   上课吗?

我正在为网络音频api创建一个基本上可以让你创作音乐的库。我有一个库的命名空间,命名空间(目前)包含几个不同的类。有score类,它充当parteffectplayer类之间的中介。 part类只是instrument的包装器,它是一个具有播放音乐功能的对象。

命名空间有一个工厂函数,它返回score的新实例,后者又有一个返回新part(s),effect(s)的工厂函数,以及最终player。此外,在任何给定时间都可以有超过1分,所以我可能会制作一个播放列表。

我最初尝试使用纯粹的功能模式,但我的代码采用了意大利面的新含义。我比命名空间/类更熟悉我的功能模式。总的来说,我一直在构建库,就像我正常的javascript文件一样,但由于增加了复杂性,一直使用commonjs模块+ browserify来轻松地将代码拆分成不同的文件/构建部件。

这个问题的具体类是part类。我希望该库在它接受的符号中非常灵活,所以我需要添加相当多的方法来解释所有这些符号(=大文件)。

3 个答案:

答案 0 :(得分:2)

我发现通过将MyClass作为参数传递给模块,我几乎可以将MyClass以外的所有内容添加到eval

似乎我可以在技术上使用{{1}}添加/访问私人会员,但我被告知这是邪恶的。只需将原型和公共方法从文件中删除就可以大大减少它,因此将私有成员留在那里是完全没问题的。

答案 1 :(得分:1)

isbn 978-0-596-80675-0(第5章对象创建模式/沙盒模式), isbn 0-596-10199-6(第10章模块和命名空间/模块实用程序)

目前,我也在寻找创建私有数据的便捷方法。我目前使用继承和defineClass的功能模式:

var defineClass = function () {
    var inheritance = function inheritance() { };
    return function defineClass(data) {
        var classname = data.name,
            superclass = data.extend || Object,
            constructor = data.construct || function () { },
            methods = data.methods || {},
            statics = data.statics || {},
            borrows,
            provides;
        if (!data.borrows) {
            borrows = [];
        }
        else {
            if (data.borrows instanceof Array) {
                borrows = data.borrows;
            }
            else {
                borrows = [data.borrows];
            };
        };
        if (!data.provides) {
            provides = [];
        }
        else {
            if (data.provides instanceof Array) {
                provides = data.provides;
            }
            else {
                provides = [data.provides];
            };
        };
        inheritance.prototype = superclass.prototype;
        var proto = new inheritance();
        for (var i = 0; i < borrows.length; i++) {
            var c = borrows[i];
            for (var p in c.prototype) {
                if (typeof c.prototype[p] != "function") continue;
                proto[p] = c.prototype[p];
            }
        }
        for (var p in methods) {
            proto[p] = methods[p];
        };
        proto.constructor = constructor;
        constructor.superclass = superclass.prototype;
        if (classname) {
            proto.classname = classname;
        };
        for (var i = 0; i < provides.length; i++) {
            var c = provides[i];
            for (var p in c.prototype) {
                if (typeof c.prototype[p] != "function") {
                    continue;
                };
                if (p == "constructor" || p == "superclass") {
                    continue;
                };
                if (p in proto && typeof proto[p] == "function" && proto[p].length == c.prototype[p].length) {
                    continue;
                };
                throw new Error("Class " + classname + " are not provided method " + c.classname + "." + p);
            };
        };
        constructor.prototype = proto;
        for (var p in statics) {
            constructor[p] = statics[p];
        };
        return constructor;
    }
}();

//SAMPLE CODE
var tempObj = function () { };
// example of a variable
tempObj.prototype.distance = 0;
// example of a method
tempObj.prototype.walk = function (time) {
    this.distance = this.distance + time * this.walkSpeed
};
tempObj.prototype.toString = function () {
    return this.name + " distance " + this.distance
};

var Animal = defineClass({
    name: "Animal",
    construct: function (name, walkSpeed) {
        this.name = name;
        this.walkSpeed = walkSpeed;
    },
    borrows: tempObj,
    methods: {
        distance: tempObj.prototype.distance
    }
});

var tempObj2 = defineClass({
    methods: {
        fly: function (time) {
            this.distance = this.distance + time * this.flySpeed
        }
    }
});

var Bird = defineClass({
    name: "Bird",
    construct: function (name, walkSpeed, flySpeed) {
        // call the parent constructor
        Bird.superclass.constructor.call(this, name, walkSpeed)
        this.flySpeed = flySpeed
    },
    extend: Animal,
    borrows: tempObj2
});

var Cuckoo = defineClass({
    name: "Cuckoo",
    extend: Bird,
    construct: function (name, walkSpeed, flySpeed) {
        // call the parent constructor
        Cuckoo.superclass.constructor.call(this, name, walkSpeed, flySpeed)
        this.word = "cucoo";
    },
    methods: {
        say: function () {
            return this.name + " says " + this.word;
        }
    }
});

var animal = new Animal("Dog", 2);
animal.walk(3);
var dd = animal.toString();             // => Dog distance 6

bird = new Bird("Bird", 1, 10);
bird.walk(3);
var ww = bird.toString();               // => Bird distance 3
bird.fly(2);
var ff = bird.toString();               // => Bird distance 23

cuckoo = new Cuckoo("Cuckoo", 1, 10);
cuckoo.walk(3);
var ww = cuckoo.toString();             // => Cuckoo distance 3
cuckoo.fly(2);
var ff = cuckoo.toString();             // => Cuckoo distance 23
var cSay = cuckoo.say();                // => Cuckoo says cucoo

答案 2 :(得分:0)

你到底是什么用例?你能举例说明你班级的作用吗?

因为采用面向对象的方式并不总是在JavaScript中做事的最佳方式。节点式模块以及函数是js中的一等公民这一事实使得它很容易实现功能。这意味着您可以导出完成一件事的单个函数。例如:

module.exports = function(x, y) {
  return x * y
}

在第二个模块中,您可以像这样使用此功能:

var add = require('./add.js')
var result = add(15, 23);

如果您想了解更多相关信息,请查看this nodeschool workshop