0

是否有必要检查代码中的所有参数和其他条件,如果我知道,我永远不会传递错误的参数并且它应该可以正常工作(比如我已经在该代码之外进行了一些检查)。

例子:

这段代码:

/**
 * Applies function to all elements of array in specified
 * context.
 * If array is empty, returns null.
 */
MyNameSpace.foreach = function(arr, callback, context) {
   if (!(arr instanceof Array)) {
       throw new Error('first argument is not an array');
   }
   if (typeof callback !== 'function') {
       throw new Error('callback is not a function');
   }
   if (typeof arr.length === 'undefined') {
      throw new Error('Length undefined');
   }

   var con = typeof context === 'object' ? context : window;

   var i = arr.length;
   if ( i <= 0 ) {
       return null;
   }

   for ( j = 0; j < i; j++ ) {
        callback.call(con, j, arr[j]);
   }
}

可能:

MyNameSpace.foreach = function(arr, callback, context) {
   var con = typeof context === 'object' ? context : window;

   var i = arr.length;
   if ( i <= 0 ) {
       return null;
   }

   for ( j = 0; j < i; j++ ) {
        callback.call(con, j, arr[j]);
   }
}
4

4 回答 4

3

绝对可以是很好的做法。它可以帮助您的应用程序的稳定性并帮助调试。缺点是它会使代码混乱(使其更难阅读)并且可能会影响性能(尽管对于大多数 JavaScript 应用程序而言,性能并不重要)。

您必须在每种情况下进行查看。这实际上取决于(1)参数不正确的可能性以及(2)如果它们不正确会造成多大的损害。

于 2011-04-09T08:51:57.723 回答
1

在测试输入和输出时,软件的一般原则是:“输入灵活,输出严格”。你应该总是对你的输入进行额外的检查,这样如果你的方法得到了它不期望的东西,你的代码就不会中断。

于 2011-04-09T08:53:37.007 回答
1

这绝对是一个好习惯,因为任何使用您的类或函数的代码都可能在不知不觉中传递给您可能导致代码崩溃的值。
例如:一位程序员曾经不小心向我的代码发送了一个 NULL 指针,该指针必须对指针指向的对象进行深层复制。
但是由于我在复制构造函数的初始化列表中克隆了指向的实例,所以没有人能弄清楚程序崩溃的原因。
程序员说我应该检查一个 NULL 指针,但最终我们决定保留他的检查,因为我们需要保持通过初始化列表复制的效率,这样更快。

因此,您可以根据以下条件决定放置检查:
1. 使用 copy-ctor 初始化列表的效率。
2. 您记录函数/类的输入参数和限制的程度如何。
3. 你的代码是否会因为恶意输入而崩溃/产生安全问题
4. 你的软件需要什么样的异常处理。

于 2011-04-09T09:10:16.020 回答
1

尽管如果在生产环境中保持启用它可能会稍微减慢执行速度,但您可以在生产环境或调试期间使用类型检查库:

function TypeEnforce (func, ctx, config) {
    if (!(this instanceof TypeEnforce)) {
        return new TypeEnforce(func, ctx);
    }
    if (typeof func === 'string' && ctx) {
        this.funcString = func;
        func = ctx[func];
    }
    this.ctx = ctx;
    this.autoset = config && config.autoset;
    this.oldFunc = func;
}
TypeEnforce.prototype.argTypes = function (args) {
    var that = this;
    this.reqArgTypesFunc = function () {
        for (var i=0, argl = args.length; i < argl; i++) {
            if (
                (args[i] === 'Array' && Object.prototype.toString.call(arguments[i]) !== '[object Array]') ||
                (args[i] !== 'Array' && typeof arguments[i] !== args[i])
            ) {
                throw 'Argument ' + i + ' [' + arguments[i] + '] should be of type ' + args[i];
            }
        }
        that.oldFunc.apply(that.ctx, arguments);
    };
    if (this.autoset) {
        this.ctx[this.funcString] = this.reqArgTypesFunc;
    }
    return this;
};
TypeEnforce.prototype.props = function (props) {
    var that = this;
    this.reqPropsFunc = function () { 
        for (var p in props) {
            if (typeof arguments[p][props[p]] === 'undefined') {
                throw 'The property "' + props[p] + '" of argument no. ' + p + 
                        ' [' + arguments[p] + '] should not be undefined';
            }
        }
        var method = that.reqArgTypesFunc || that.oldFunc;
        method.apply(that.ctx, arguments);
    };
    if (this.autoset) {
        this.ctx[this.funcString] = this.reqPropsFunc;
    }
    return this;
};
TypeEnforce.prototype.get = function (props) {
    return this.reqPropsFunc || this.reqArgTypesFunc || this.oldFunc;
};

...在您的情况下,您可以按如下方式使用:

if (!MyNameSpace) {
    var MyNameSpace = {};
}
MyNameSpace.foreach = function(arr, callback, context) {
   var con = typeof context === 'object' ? context : window;

   var i = arr.length;
   if ( i <= 0 ) {
       return null;
   }

   for ( j = 0; j < i; j++ ) {
        callback.call(con, j, arr[j]);
   }
};

TypeEnforce('foreach', MyNameSpace, {autoset:true}).
    argTypes(['Array', 'function']).
    props({0:'length'});

MyNameSpace.foreach(['a', 'b'], function (k, v) {
    alert(k+':'+v);
});

使用这种方法,您可以分离出丑陋的类型检查代码,如果您只在测试期间需要它,甚至可以禁用它。您可以进一步添加用于参数或属性值检查的方法。

于 2011-04-09T14:31:32.577 回答