在程序的范围内,首选放置JavaScript实用程序类?

时间:2012-07-03 00:17:55

标签: javascript oop design-patterns

我正在开发一个有点大规模的JS应用程序,我想将一些常用函数分解为实用程序类。然而,我不清楚我应该怎么做。

例如,假设我有一堆基于形状的类需要在实用程序类中调用函数:

// Triangle class
Triangle.prototype = new Shape();
Triangle.prototype.constructor = Triangle;

function Triangle() {...}
Triangle.prototype.drawOutline = function() {
  var outline = Utility.canvas.trace(this._canvas); // Trace the shape.
  this._viewport.drawImage(outline, 0, 0); // Draw the traced outline.
}

// Circle class
Circle.prototype = new Shape();
Circle.prototype.constructor = Circle;

function Circle() {...}
Circle.prototype.drawOutline = function() {
  var outline = Utility.canvas.trace(this._canvas); // Trace the shape.
  this._viewport.drawImage(outline, 0, 0); // Draw the traced outline.
}

在全局级别实例化Utility类是否有意义?我觉得应该有一个额外的级别,比如Application,所以我有Application.UtilityApplication.UI等等。不幸的是,走这条路线迫使每个专门的形状类知道更大的程序结构是什么(所以它可以引用Application.Utility),这不是很好。

是否有更好的,首选的方式让专门的JS类使用未继承的通用类函数?


编辑:可能有助于说我正在尝试将其与C ++或Java中的#includeimport语句相关联。在JS中最好的方法是什么?

4 个答案:

答案 0 :(得分:3)

假设您将所有代码都包装在一个匿名函数中,那么我通常只需创建一个对象(命名空间)并将所有的函数放在那里:

;(function(){

  var Utils = {
    triangle: function () { ... },
    circle: function () { ... }
  }

}())

然后,无论何时使用它,您只需按照您知道何时使用utils的方式进行Utils.circle(...),并且可以轻松跟踪它们,添加新的等等。

  

可能有助于说我正在尝试将此与#include或   来自C ++或Java的import语句。什么是最好的方式   这在JS?

在这种情况下,最简单的方法是创建concat.sh文件或类似文件以及start.jsend.js,并在其间添加所有内容。

<强> start.js

;(function(){

<强> utils.js

var Utils = {
  triangle: function () { ... },
  circle: function () { ... }
}

<强> end.js

}())

<强> concat.sh

当然,订单很重要。

#!bin/bash
cat start.js utils.js end.js > out.js

如果您正在进入node.js,请查看grunt,只需很少的配置即可为您完成所有这些工作。

否则,对于更高级的东西,请使用CommonJS模块。

答案 1 :(得分:1)

命名空间的最大原因是避免库之间的冲突。就个人而言,我用dt写的所有内容都是前缀。所以我有dt.Utility。选择一个前缀并继续使用它。 =)

答案 2 :(得分:1)

问题实际上可能是实用程序类,实际上不应该是实用程序类。也许最好做这样的事情:

// Triangle class
Triangle.prototype = new Shape();
Triangle.prototype.constructor = Triangle;

function Triangle() {...}
Triangle.prototype.drawOutline = function() {
}

// Circle class
Circle.prototype = new Shape();
Circle.prototype.constructor = Circle;

function Circle() {...}
Circle.prototype.drawOutline = function() {
}

function OutlineDrawer(shape)
{
    this.shape = shape;
}

OutlineDrawer.prototype.draw(viewport)
{
    var outline = Utility.canvas.traceShape(this.shape.canvas()); // Trace the shape.
    viewport.drawImage(outline, 0, 0); // Draw the traced outline.
}

你对形状负有很大的责任。形状应该定义该特定形状实例的属性,但您应该使用不同的类来跟踪它们。您可能希望将相同的形状绘制到不同的视图端口(例如,将其保存到文件中),或使用不同的算法绘制相同的场景(以调整速度与性能和质量)。等...

答案 3 :(得分:0)

与其他答案相同。

将你的原型放在一个全局对象中(我知道,它不是很推荐,但它是一个特例)。


// Utils.js

// treat this global object as a "namespace" or "module"
var Utils = 
{

  // Triangle class
  Triangle.prototype = new Shape();
  Triangle.prototype.constructor = Triangle;

  function Triangle() {...}
    Triangle.prototype.drawOutline = function() {
    var outline = Utility.canvas.traceShape(this._canvas); // Trace the shape.
    this._viewport.drawImage(outline, 0, 0); // Draw the traced outline.
  }

  // Circle class
  Circle.prototype = new Shape();
  Circle.prototype.constructor = Circle;

  function Circle() {...}
    Circle.prototype.drawOutline = function() {
    var outline = Utility.canvas.traceShape(this._canvas); // Trace the shape.
    this._viewport.drawImage(outline, 0, 0); // Draw the traced outline.
  }
} // var Utils

// anotherfile.js

var MyTriangle = new Utils.Triangle();
var MyCircle  =  new Utils.Triangle();

这个技巧,它被称为“模块软件设计模式”。