【问题标题】:nested class definition without creating additional global objects嵌套类定义而不创建额外的全局对象
【发布时间】:2012-04-05 09:37:57
【问题描述】:

我正在尝试在 javascript 中创建嵌套类定义,使其只有一个全局对象。

目前我们定义这样的新类:

FOO.Navigation.Sidebar.Tooltip = function()
{
};

所以在每个函数定义中我们必须重复整个嵌套类命名空间:

FOO.Navigation.Sidebar.Tooltip.prototype.show = function()
{
  /* do something here */
};

我们引入了一个命名空间函数来创建类。

FOO = { /* ... */ }

FOO.namespace = function(namespaceString)
{
  var namespaceParts = namespaceString.split('.');
  var currentRoot = FOO;
  var index = 0;

  // Skip the first namespacePart, if it is already "FOO"
  if ("FOO" == namespaceParts[0])
  {
  index = 1;
  }

  var currentPart;  
  for(index; index < namespaceParts.length; index++)
  {     
    // This is the next element in the namespace hierarchy.
    currentPart = namespaceParts[index]; 
    // Add a new map for the currentPart to the root (if it does not exist yet). 
    currentRoot[currentPart] = currentRoot[currentPart] || {};
    // The currentPart will be the new root in the next loop.
    currentRoot = currentRoot[currentPart];
  }

  return currentRoot;
};

现在我们想用它来创建一个更易读的先前定义的版本,应该如下所示:

FOO.Navigation.Sidebar.Tooltip = function()
{
  this.hallo = "world";
};

var tooltip = FOO.Navigation.Sidebar.Tooltip;

tooltip.prototype.show = function()
{
  /* do something */
};

这将创建一个新的全局变量“工具提示”,我们必须输入两次类名。 所以我们想用这样的匿名函数:

(function(tooltip) {
  tooltip = function()
  {
    this.hello = "world";
  };

  tooltip.prototype.show= function()
  {
    /* do something */
  };
}) (FOO.namespace("FOO.Navigation.Sidebar.Tooltip"))

这显然行不通,因为我们为“工具提示”分配了一个新的函数定义。

所以我的问题是,是否有办法只编写一次类名而不创建更多全局变量。

【问题讨论】:

  • 我会提醒您,您正在编写 JavaScript,而不是 Java。所有这些foo.bar.baz.trev.cat.mouse 命名空间malarkey 都不属于JavaScript。
  • 好吧,我们正在努力使我们的 C++ 开发人员更容易访问该框架。这就是为什么我们尽量避免使用额外的全局变量等。

标签: javascript class global-variables nested-class


【解决方案1】:

在我看来,您正在尝试创建 Module Pattern 的实现。模块一般用于创建单实例对象;但是您可以轻松地将工厂方法添加到返回新闭包(函数)的模块中。

使用上面粘贴的代码,您可以直接将方法附加到闭包内提供的tooltip 变量;例如:

(function(Tooltip) {
    // 'Static' method added to the module definition.
    Tooltip.hello = function() { 
        alert("Hello!");
    };

    // Factory method which returns a new object.
    Tooltip.create(message) {
        return { 
            this.message = message;
            this.show = function() { /* ... */ }
        };
    }
})(FOO.namespace("FOO.Navigation.Sidebar.Tooltip"));

然后就可以调用Tooltip上的hello方法了:

// Invoke a static method.
FOO.Navigation.Sidebar.Tooltip.hello();​

// Create a new ToolTip instance.
var myToolTip = FOO.Navigation.Sidebar.Tooltip.create("Hello World");
myToolTip.show();

如果您想创建一个分层的类结构,那么您可能需要考虑一个常见的 JavaScript 库,例如 Backbone.js

【讨论】:

  • 是的,你是对的,但没有像这样定义构造函数。
  • 嗨 Stefan,我已经更新了我的答案,包括对模块模式的引用和添加工厂方法。在我看来,更经典的 OOP 设计可能会更好地为您服务(有人说这与 JavaScript 的语言背道而驰)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 2020-04-21
  • 2022-08-05
  • 2014-01-10
相关资源
最近更新 更多