【问题标题】:JavaScript inheritance with Require.js and the Revealing Module Pattern使用 Require.js 和显示模块模式的 JavaScript 继承
【发布时间】:2015-04-24 06:55:33
【问题描述】:

问题:

一个看似简单的问题,我在过去 2 周里断断续续地研究(请放轻松,因为我是新手!):

在使用 Require.js 和 Revealing Module Pattern 时,如何在 JavaScript 中巧妙地实现继承?


示例:

这是一个示例模块,它是某种类型的“Component”的基类:

define('Component', [], function () {
   "use strict";

   var _privateVar = 10;
   var _doPrivateThings = function () {  /* do stuff */ };    
   var init = function () { /* do stuff */ };
   var update = function () {  /* do stuff */ };

   return {
      init : init,
      update : update
   };

});

接下来我要实现 CakeComponent,它应该继承 Component 的所有内容,并允许我编辑/添加方法和属性:

define('CakeComponent', ['Component'], function (Component) {
   "use strict";
   
   // Setup inheritance
   var CakeComponent = function() {}
   CakeComponent.prototype = new Component();

   // Add/edit methods/properties
   CakeComponent.prototype.newMethod = function () { /* do stuff */ };

   return {
      init : CakeComponent.init,
      update : CakeComponent.update,
      newMethod : CakeComponent.newMethod
   };

});

首先,我不确定这是否完全有意义,但其次,我的 CakeComponent 感觉有点恶心,因为现在我到处都有这个 CakeComponent 冗余,我不得不“重新显示”@ 987654329@ 和 update 方法。

我真的更喜欢这样的东西(我意识到这没有意义,它实际上只是伪代码):

define('CakeComponent', ['Component'], function (Component) {
   "use strict";

   this.extends(Component);
   var newMethod = function () { /* do stuff */ };

   return {
      newMethod : newMethod
   };

});

任何提示或建议将不胜感激。谢谢。


更多详情

  • 也许我应该总是在define 包装器中创建一个类对象?我见过有人这样做,但在我遇到这个问题之前似乎没有必要。
  • 函数对象上的.call() 方法在这种情况下是否有用?例如使用Component.call()
  • @Bergi 请见下文:

define([], function () {
    "use strict";

    var Component = function () {

        var _privateVar = 10;
        var _doPrivateThings = function () {  /* do stuff */ };
        this.init = function () { /* do stuff */ };
        this.update = function () {  /* do stuff */ };

    };

    return Component;

});

【问题讨论】:

  • new Component(); 似乎根本不起作用,您的 Component 是模块对象而不是类构造函数?
  • @Bergi 是的,我以前读过,谢谢,但我的问题实际上是 requirejs,而不仅仅是 RVP 的继承或受保护的变量。嗯,我会看看为什么它不起作用,谢谢
  • 你真的想要类(可多次实例化)还是模块对象(单例)?在第一种情况下,您需要 return 来自您的 definer 函数的构造函数,而不是您当前所做的对象文字。如果你想拥有模块,你所说的“继承”是什么意思?
  • 是的,就是这样。现在,您可以通过将原型用于不需要特权的方法来扩展该模式,您可以inherit from the "class" as always

标签: javascript inheritance requirejs revealing-module-pattern


【解决方案1】:

我以前见过这种模型,叫做通用模块定义:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['Component'], factory);
    } else {
        root.CakeComponent = factory(root.Component);
    }
}(this, function (Component) {
    return {
        newMethod: function(){ /* do stuff */ }
    };
}));

你可以试试这个,这不是“真正的”继承——万一它不起作用——取决于环境,你可能还需要传递基本函数,这很遗憾:

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['Component'], factory);
    } else {
        root.CakeComponent = factory(root.Component);
    }
}(this, function (Component) {
    return {
        init: Component.init,
        update: Component.update,
        newMethod: function(){ /* do stuff */ }
    };
}));

您可以在这篇关于 Universal Module Definition 的精彩文章中阅读有关此主题的更多信息

【讨论】:

  • 哦,哇,这看起来很狡猾——你说的取决于环境是什么意思?就像在浏览器与 node.js 中一样?您认为在每个模块中定义一个类对象(例如var Component = function() { ... })会更好吗?
  • @JoeRocc 没错,实际上 node.js 的实现看起来有点不同。在每个模块中重新定义组件听起来不是一个好主意。 RequireJS 应该能够连接到这一点。仔细阅读这篇关于通用模块定义的文章:dontkry.com/posts/code/…
  • @hexeri_software 据我了解,那篇文章建议不要使用 UMD,而是选择一个定义,然后使用构建(浏览器)来决定后期制作中的最终模块定义?我不确定这有什么帮助?
  • @JoeRocc 文章的底部是一个品味问题,我更多地指的是顶部。 BUT 试试这个:这里有不同的全局浏览器、node 和 commonJS 解决方案,都兼容 requireJS:github.com/umdjs/umd
  • 谢谢你,虽然我不确定这对我的继承有何帮助? @Bergi 上面评论说,如果我想获得正确的继承,我可能需要从 define 工厂返回一个构造函数,并且(我认为)使用原型。你对此有何看法?我并没有真正意识到“模块”范式更加面向单例
猜你喜欢
  • 2013-05-15
  • 2023-03-21
  • 2014-08-11
  • 1970-01-01
  • 2013-09-19
  • 2013-04-28
  • 2014-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多