0

编辑:我发现了这个有趣的库,看起来它可以完全按照我在底部所描述的:https ://github.com/philbooth/check-types.js

看起来你可以通过调用 check.quacksLike 来做到这一点。


我对使用 javascript 还很陌生,我很喜欢它提供的强大功能,但有时它太灵活了,我的理智无法处理。我想要一种简单的方法来强制某些参数尊重特定的接口。

这是一个简单的示例方法,突出了我的问题:

var execute = function(args)
{
    executor.execute(args);
}

假设 executor 期望args有一个名为 的属性cmd。如果未定义,则当程序尝试引用cmd但它是undefined. cmd与在此方法中显式强制 ' 的存在相比,这样的错误调试起来会更烦人。执行者甚至可能期望它args有一个被调用的函数getExecutionContext(),它会被传递一点。我可以想象更复杂的场景,调试将很快成为追踪函数调用以查看第一次传入参数的位置的噩梦。

我也不想做以下事情:

var execute = function(args)
{
    if(args.cmd === undefined || args.getExecutionContext === undefined ||
       typeof args.getExecutionContext !== 'function')
        throw new Error("args not setup correctly");
    executor.execute(args);
}

这将需要对每个具有参数的函数进行大量维护,特别是对于复杂参数。我宁愿能够指定一个接口并以某种方式强制执行一个合同,告诉 javascript 我希望输入匹配这个接口。

也许是这样的:

var baseCommand =
{
    cmd: '',
    getExecutionContext: function(){}
};

var execute = function(args)
{
    enforce(args, baseCommand); //throws an error if args does not honor
                                //baseCommand's properties
    executor.execute(args);
}

然后,我可以在我的不同函数中重用这些接口,并定义扩展它们以传递到我的函数的对象,而不必担心拼写错误的属性名称或传入错误的参数。关于如何实现这一点,或者我可以在哪里利用现有实现的任何想法?

4

3 回答 3

0

我没有看到任何其他方式来强制执行此操作。这是 JavaScript 动态特性的副作用之一。它本质上是免费的,随着这种自由而来的是责任:-)

于 2013-07-19T01:20:55.083 回答
0

如果您需要类型检查,您可以查看 typescript(它不是 JavaScript)或 google 的闭包编译器(带有注释的 JavaScript)。

闭包编译器使用注释来确定编译时预期的类型。看起来很麻烦,但在大型项目中可能会有所帮助。

闭包编译器还有其他好处,因为您将被迫生成在像 netbeans 这样的 IDE 中使用的注释,它会缩小您的代码,删除未使用的代码并扁平化命名空间。因此,在命名空间中组织的代码myApp.myModule.myObject.myFunction将被展平以最小化对象查找。

缺点是当您使用与 jQuery 等编译器不兼容的库时,您需要使用 externs。

于 2013-07-19T01:31:20.807 回答
0

在 javascript 中处理这种事情的方式通常是使用默认值。大多数情况下,您只是想保证某些成员存在以防止诸如引用错误之类的事情,但我认为您可以使用主体来获得您想要的东西。

通过使用类似 jQuery 的 extend 方法,我们可以保证一个参数实现了一组定义的默认值。

    var defaults = {
        prop1: 'exists',
        prop2: function() { return 'foo'; }
    };

    function someCall(args) {
        var options = $.extend({}, defaults, args);
        // Do work with options... It is now guarentee'd to have members prop1 and prop2, defined by the caller if they exist, using defaults if not.
    }

如果您真的想在未提供特定成员的情况下在运行时抛出错误,您也许可以定义一个抛出错误的函数,并将其包含在您的默认值中。因此,如果调用者提供了一个成员,它将覆盖默认值,但如果它被遗漏,它可能会采用一些默认功能或根据需要抛出错误。

于 2013-07-19T03:15:42.977 回答