Хотя это может немного замедлить выполнение, если вы оставите его включенным в производственной среде, вы можете использовать библиотеку проверки типов, как в производственной, так и во время отладки:
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);
});
При таком подходе вы можете выделить уродливый код проверки типа и даже отключить его, если он понадобится вам только во время тестирования. Вы также можете добавить методы для проверки аргумента или значения свойства.