建设者可以帮帮我吗? (即JavaScript中的构造函数有什么用?)

时间:2013-05-25 16:07:55

标签: javascript

我已经使用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中的构造函数有什么用?如果强类型或强制封装没有实用选项,那么为什么要使用构造函数呢?在这种情况下,我似乎无法弄清楚如何使用成员函数来改善我的生活,因此“继承”似乎并不是非常有用。

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

1 个答案:

答案 0 :(得分:0)

虽然JavaScript是动态和弱类型的,但似乎运算符new的使用是Brendan Eich抛出的设备,当他真正想要一个Scheme时,使语言看起来更像C和Java类似于开头的语言(有关此apochryphal故事的更多信息,请参阅this post by Brendan Eich),您可能从构造函数中获得一些优势:

  1. 很多人从JavaScript开始就使用构造函数,并且很容易理解你的代码。

  2. 在创建对象的表达式中使用 new 运算符看起来就像是在创建一个新对象。如果您的函数被称为XmlAttributeTable,并且您在不使用new的情况下将其称为函数,那么您创建任何内容都不太清楚。也就是说,如果您调用方法newTablecreateTablemakeTable,那也可以。

  3. 如果您使用Object.create,构造函数会带来一点魔力,您需要额外的代码行才能实现。这包括简化构造并使原型具有随时可用的构造函数属性。

  4. 考虑:

    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声称在为期10天的JavaScript设计中犯了一些“错误”(参见他在JSConf 2010上的主题演讲),但我从未听过他对构造函数的遗憾。

    因此,恕我直言,构造函数式的编码可以帮助您提高可读性,特别是如果您创建的大量对象都属于同一类型。但是,这种风格可能不适合你。

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

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

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

      当你问“代码味道”时,我可能会在没有getter方法的情况下做。现代JavaScript允许您使用get属性创建属性,当您想要读取属性并执行代码时,该属性是干净的。更好的恕我直言,而不是命名一个陈述get的方法。此外,如果你的吸气剂不只是访问一个属性,你可以找到一个更好的名字。