0

我使用 Google 图表 + jQuery API 编写了一些不错的包装器,当您将鼠标悬停时它们会进行很好的更新。我目前正在重构我的代码。我有返回具有属性的对象的函数,这些属性本身具有其他属性,依此类推。有很多函数返回包含属性对象的数组,其中一些是数组等。

这是我的代码示例,它从 ajax XML 树加载 ROC 和似然表的集合:

function XMLAttributeTable(subtree, point_name, arr_of_attributes) {
    // note: assumes numeric attribute values
    var attributes_for_each_point = [];
    $(subtree).find(point_name).each(function() {
    row = $(this);
    var point = {};
    arr_of_attributes.forEach( function(attr_name) { 
        point[attr_name] = parseFloatPlus(row.attr(attr_name));
    });
    attributes_for_each_point.push(point);
    });

    return attributes_for_each_point;
}

function XMLAttributeTableCollection(subtree, instance_name, point_name, arr_of_attributes) {
    // note: assumes the series are in order
    var tables_for_each_instance = [];
    $(subtree).find(instance_name).each( function() {
    tables_for_each_instance.push( XMLAttributeTable( this, "point", arr_of_attributes ) );
    });
    return tables_for_each_instance;
}

function getROCSeriesForEachRanking(roc_subtree) {
    return XMLAttributeTableCollection(roc_subtree, 'roc_series', 'point', ['index', 'target_groups', 'q_value']);
}

function getLikelihoodSeriesForEachRanking(likelihood_subtree) {
    return XMLAttributeTableCollection(likelihood_subtree, 'likelihood_series', 'point', ['index', 'likelihood']);
}

这些功能有很多,我并不是很喜欢这个(分离关注点感觉非常困难)。我可能对尝试使用其他语言(即 C++)的语义来编写 JavaScript 感到内疚,如果是这样,感谢您的建议。但我无法摆脱有代码气味的感觉。

所以我的问题是,JavaScript 中的构造函数有什么好处?如果没有强类型或强制封装的实用选项,那么为什么要使用构造函数呢?在这种情况下,我似乎无法弄清楚如何使用成员函数来改善我的生活,因此“继承”似乎不是很有用。

非常感谢您提供的任何建议。

4

1 回答 1

0

尽管 JavaScript 是动态且弱类型的,但使用运算符似乎new是 Brendan Eich 为使语言看起来更像 C 和 Java 而在他真正想要一种类似于 Scheme 的语言时投入的一种手段(参见这篇由 Brendan Eich撰写的关于这个虚构故事的更多信息),您可能会从构造函数中获得一些优势:

  1. 自 JavaScript 早期以来,很多人一直在使用构造函数,并且很容易理解您的代码。

  2. 在创建对象的表达式中使用new运算符看起来就像是在创建一个新对象。如果您的函数被调用XmlAttributeTable并且您在没有使用的情况下将其作为函数调用new,那么您正在创建任何东西都不是很清楚。也就是说,如果你调用你的方法,或者newTable然后那也可以。createTablemakeTable

  3. 构造函数带有一点魔力,如果你使用Object.create. 这包括简化构造并使原型具有随时可用的构造函数属性。

考虑:

function Point(x, y) {
    this.x = x
    this.y = y
}

相对

function makePoint(x, y) {
    var point = Object.create(theProtoPointIDeclaredEarlier);
    point.x = x;
    point.y = y;
    return this;
}

我已经阅读了好几次Object.create应该优先使用的内容new,但实际上我并不认为操作员new如此邪恶。我知道很多人可能不同意这里,这很好。Eich 声称在 JavaScript 的 10 天设计中犯了一些“错误”(请参阅​​他在 JSConf 2010 上的主题演讲),但我从未听说他对构造函数感到遗憾。

因此,恕我直言,构造函数风格的编码可以帮助您提高可读性,尤其是在您创建大量似乎都属于同一类型的对象时。但是,这样的风格可能不适合你。

  1. 如果您有许多一次性对象,它们看起来并不都属于相同的“类型”,那么请避免使用构造函数并将对象作为命名属性的容器来处理。这完全没问题。

  2. 请记住,JavaScript 不是基于类的 OOP 语言,因此如果您需要派生属性,请使用原型。在 JavaScript 这样的语言中,继承并不是你会非常关心的事情(Crockford 在几个不同的地方很好地说明了这一点)。但是,仅仅因为继承对您没有帮助,所以不需要构造函数是错误的。可以在不进行任何继承的情况下使用构造函数。

因此,无论您是否要使用构造函数,恕我直言,归结为您是否有很多看起来相同的对象与是否有一次性对象。但是你可以很容易地没有它们。特别是在前一种情况下,原型对象可以很好地保持常见行为。但是您也可以将常见行为放在原型Object.create中。

当您询问“代码气味”时,我可能不会使用 getter 方法。现代 JavaScript 允许您使用属性创建get属性,当您想要读取属性并执行代码时,这很干净。恕我直言,比用get. 此外,如果您的 getter 不只是访问属性,您可以找到更好的名称。

于 2013-05-25T16:56:06.253 回答