代码之家  ›  专栏  ›  技术社区  ›  fearless_fool

如何跨node.js中的多个文件拆分类定义?

  •  8
  • fearless_fool  · 技术社区  · 10 年前

    我的类定义 Foo 已经发展到我想将其拆分为多个文件的程度。例如,我想要这样的东西:

    // file foo.js
    'use strict';
    function Foo() { };
    Foo.prototype.constructor = Foo;
    Foo.prototype.methodA = function() { console.log('methodA'); };
    module.exports = Foo;
    
    // file foo-aux.js
    'use strict';
    Foo.prototype.methodB = function() {
      console.log('methodB');
      this.methodA();
    };
    
    // file main.js
    'use strict';
    const Foo = require('./foo');
    var foo = new Foo();
    foo.methodB();
    

    什么是正确的组合 module.export require() 使上述代码工作?

    2 回复  |  直到 10 年前
        1
  •  10
  •   Community Mohan Dere    9 年前

    更新的答案

    (全方位支持 McMath's detailed answer --它比下面的原始答案具有更好的伸缩性,并提供了更好的代码重用机会。它促使我更新了这个答案。但是,如果您不需要在那里支持完整的混合路线,这里有一个干净而简单的方法。)

    修改 technique suggested by Shaun Xu require 将在拆分文件中接收。

    最好使用 index.js 保存类定义和子文件——这表明子文件是 Foo 类别:

    main.js
    foo/
      index.js
      foo-a.js
      foo-b.js
    

    具有以下功能:

    // foo/index.js
    'use strict';
    function Foo() {};
    Foo.prototype.constructor = Foo;
    require('./foo-a')(Foo);
    require('./foo-b')(Foo);
    module.exports = Foo;
    
    // foo/foo-a.js
    'use strict';
    module.exports = function(Foo) { 
      Foo.prototype.methodA = function() {
        console.log('methodA');
      };
      // more methods as desired...
    };
    
    // foo/foo-b.js
    'use strict';
    module.exports = function(Foo) { 
      Foo.prototype.methodB = function() {
        console.log('methodB');
        this.methodA();
      };
      // more methods as desired...
    };
    

    并称之为:

    // main.js
    'use strict';
    const Foo = require('./foo/');
    var foo = new Foo();
    foo.methodB();
    

    原始答案

    // file foo.js
    'use strict';
    function Foo() { };
    Foo.prototype.constructor = Foo;
    Foo.prototype.methodA = function() { console.log('methodA'); };
    require('./foo-aux')(Foo);  // <== add this line
    module.exports = Foo;
    
    // file foo-aux.js
    'use strict';
    module.exports = function(Foo) {  // <== wrap function definitions 
      Foo.prototype.methodB = function() {
        console.log('methodB');
        this.methodA();
      };
    };
    
    // file main.js
    'use strict';
    const Foo = require('./foo');
    var foo = new Foo();
    foo.methodB();
    
    // test
    $ node foo.js
    methodB
    methodA
    
        2
  •  7
  •   McMath    10 年前

    我会考虑两种解决方案,这取决于我是想为每个文件定义一个方法,还是将多个相关方法分组到一个文件中。

    每个文件一个方法

    从如下目录结构开始:

    foo/
      foo.a.js
      foo.b.js
      index.js
    main.js
    

    的方法之一 Foo 可能如下所示:

    // foo/foo.a.js
    
    module.exports = function() {
      console.log('Method A');
    };
    

    另一种方法可以用类似的方式定义。 其本身可以这样定义:

    // foo/index.js
    
    function Foo() { }
    
    Foo.prototype.methodA = require('./foo.a');
    Foo.prototype.methodB = require('./foo.b');
    
    module.exports = Foo;
    

    现在我们可以使用 这样地:

    // main.js
    
    var Foo = require('./foo');
    
    var foo = new Foo();
    
    foo.methodA(); // 'Method A'
    foo.methodB(); // 'Method B'
    

    与您自己的解决方案相比,此解决方案的一个优点是 在一个地方声明,即 foo/index.js ,但在别处定义。看看一个文件,很明显什么方法 有,没有实现的所有杂乱。

    每个文件有多个方法

    在这种情况下,我倾向于使用 mixin

    /foo
      bar.js
      baz.js
      index.js
    /utils
      extend.js
      mixin.js
    main.js
    

    从一个用另一个对象扩展一个对象的函数开始,包括getter/setter并维护相同的 property descriptor .

    // utils/extend.js
    
    module.exports = function extend(target, source) {
      var names = Object.getOwnPropertyNames(source);
      var len = names.length;
    
      for (var i = 0; i < len; i++) {
        var name = names[i];
        var descriptor = Object.getOwnPropertyDescriptor(source, name);
    
        Object.defineProperty(target, name, descriptor);
      }
    };
    

    mixin只对两个对象的原型执行此操作:

    // utils/mixin.js
    
    var extend = require('./extend');
    
    module.exports = function mixin(target, source) {
      extend(target.prototype, source.prototype);
    };
    

    现在我们可以定义 Bar 基类如下:

    // foo/bar.js
    
    function Bar(a, b) {
      this.a = a;
      this.b = b;
    }
    
    Bar.prototype.methodA = function() {
      console.log(this.a);
    };
    
    Bar.prototype.methodB = function() {
      console.log(this.b);
    };
    
    module.exports = Bar;
    

    Baz 可以类似地定义。然后 ,可以这样定义:

    // foo/index.js
    
    var Bar = require('./bar');
    var Baz = require('./baz');
    var mixin = require('../utils/mixin');
    
    function Foo(a, b, c, d) {
      Bar.call(this, a, b);
      Baz.call(this, c, d);
    }
    
    mixin(Foo, Bar);
    mixin(Foo, Baz);
    
    module.exports = Foo;
    

    我们可以这样使用它:

    // main.js
    
    var Foo = require('./foo');
    
    var foo = new Foo('one', 'two', 'three', 'four');
    
    foo.methodA(); // 'one'
    foo.methodB(); // 'two'
    foo.methodC(); // 'three'
    foo.methodD(); // 'four'
    

    这种方法的一个优点是,我们可以 酒吧 巴兹 或者扩展其他类。此外,每个构造函数都有自己的构造函数,这让我们可以在定义它们的文件中声明它们的依赖项,而不必记住分配 this.a 中的属性 构造函数。

    推荐文章