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

本番環境で有効にしておくと実行が少し遅くなる可能性がありますが、本番環境またはデバッグ中に型チェック ライブラリを使用できます。

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 に答える
1

入力と出力のテストに関するソフトウェアの一般原則は、「入力には柔軟に、出力には厳密に」です。メソッドが予期しないものを取得した場合にコードが壊れないように、常に入力に対して追加のチェックを行う必要があります。

于 2011-04-09T08:53:37.007 に答える