JavaScript - 推荐可测试模式

时间:2010-10-15 16:31:42

标签: javascript

我阅读了2个JavaScript可测试模式,但我不确定它们有何区别以及我应该使用哪个模式。

模式1:

function class () {
    this.propertyA = null;
    this.methodA = function() {
        alert('');
    }
}

var object = new class();
object.methodA();

模式2:

var object = (function() {
    var propertyA = null;
    return {
        methodA: function() {
            alert('');
        }
    }
}());
var object = new class();
object.methodA();

有什么区别?我应该用jQuery的QUnit进行单元测试?请注意,jQuery插件不是我的要求的选项(不是UI测试,仅限业务逻辑)。谢谢。

2 个答案:

答案 0 :(得分:2)

这些模式之间的区别在于第二种模式“隐藏”了内部属性 - 一旦有了对象,就无法访​​问propertyA,只能调用methodA(它本身可以访问propertyA)。因此,从面向对象的封装角度来看,模式2更好。

在测试方面,它应该不重要,因为你应该根据你的“公共”API进行测试 - 你在测试中调用的方法应该是你的对象的用户可以调用的方法 - 以及两种模式应该是相同的。但我可以想象一个场景,只是为了测试,你可能需要从“外部”设置propertyA。这可能表明存在设计问题。但是如果你不能重新设计以防止出现这种情况,那么你需要使用模式1。

答案 1 :(得分:2)

QUnit并不关心这种或那种方式。它基本上是一个为断言提供漂亮输出的包装器。

至于两种模式之间的区别,模式1(正如您已实现的那样)具有全公共属性。但是你可以做私人财产:

function class () {
    var propertyA = null;
    this.methodA = function() {
        alert('');
    }
}

var object = new class();
object.methodA();

模式2实际上不起作用。您只是提供一个包含在闭包中的结果对象,因此您无法真正调用new。你需要这样做:

var class = (function() {
    var propertyA = null;
    return function () {
        return {
            methodA: function() {
                alert('');
            }
        };
    }
}());
var object = new class();
object.methodA();

new关键字的重点在于它使用绑定到this的新变量调用对象的构造函数。如果你没有构造函数,那么你只需创建一个单例。

出于实际目的,这是正在发生的事情:

  • 在模式1中,为每个类实例创建一个新的propertyA
  • 在模式2中(当你实现它时),你正在创建一个单例对象。
  • 在模式2中(我实现它),在所有实例之间共享一个propertyA(如C ++中的静态成员)。

这是因为在模式1中你创建了一个简单的构造函数,它为new的每次调用创建了一个围绕公共方法的新闭包。在模式2中,您在构造函数周围创建一个闭包,并在构造函数范围之外声明变量。