我尝试在我的应用程序中使用,简单的比较器通过传递字符串过滤器来过滤一些数据而不是例如。传递给[].filter
比较器应该返回一个过滤器的功能。
var comparator = function( a, b, c ) {
switch( b ){
case '>=': return function() { return this[a] >= c;}; break;
case '<=': return function() { return this[a] <= c;}; break;
case '<': return function() { return this[a] < c;}; break;
case '>': return function() { return this[a] > c;}; break;
case '=': return function() { return this[a] == c;}; break;
case '==': return function() { return this[a] === c;}; break;
case '!=': return function() { return this[a] != c;}; break;
default: return null;
};
}
假设我通过以下方式获得此功能:
var filterFn = comparator.apply({}, /(.+)(=|>=|<=|<|>|!=|==|!==)(.+)/.exec( "id<4" ).slice(1) );
someModel = someModel.objects.filter( filterFn );
它看起来的目标:
someModel.get = function( filter ){
return new Model(
this.objects.filter(
comparator.apply({}, /(.+)(=|>=|<=|<|>|!=|==|!==)(.+)/.exec( "id<4" ).slice(1)
)
);
};
var filtered = someModel.get( "id<4" );
问题是 - 我认为它将会有更多的运营商,我不知道如何更简单地写它。
使用Eval是不可能的。
这段代码没有被执行和测试我写它只是为了表明我的意思。
答案 0 :(得分:5)
将每个函数存储在对象中,可以是预定义的,也可以是动态的。
如果您想动态创建一组函数,请定义comparator
对象,如下所示。我以为你没有扩展Object.prototype
。如果您这样做,则必须在第一个循环中使用operators.hasOwnProperty(property)
。
// Run only once
var funcs = {}; // Optionally, remove `funcs` and swap `funcs` with `operators`
var operators = { // at the first loop.
'>=': '>=',
'<=': '<=',
'<' : '<',
'>' : '>',
'=' : '==', //!!
'==':'===', //!!
'!=': '!='
}; // Operators
// Function constructor used only once, for construction
for (var operator in operators) {
funcs[operator] = Function('a', 'c',
'return function() {return this[a] ' + operator + ' c};');
}
// Run later
var comparator = function(a, b, c) {
return typeof funcs[b] === 'function' ? funcs[b](a, c) : null;
};
调用comparator
时,返回的函数如下所示:
function() { return this[a] < c; }// Where a, c are pre-determined.
此方法可以通过这种方式实现( demo at JSFiddle ):
// Assumed that funcs has been defined
function implementComparator(set, key, operator, value) {
var comparator, newset = [], i;
if (typeof funcs[operator] === 'function') {
comparator = funcs[operator](key, value);
} else { //If the function does not exist...
throw TypeError("Unrecognised operator");
}
// Walk through the whole set
for (i = 0; i < set.length; i++) {
// Invoke the comparator, setting `this` to `set[i]`. If true, push item
if (comparator.call(set[i])) {
newset.push(set[i]);
}
}
return newset;
}
var set = [ {meow: 5}, {meow: 3}, {meow: 4}, {meow: 0}, {meow: 9}]
implementComparator( set , 'meow', '<=', 5);
// equals: [ {meow: 5}, {meow: 3}, {meow: 4}, {meow: 0} ]
为了澄清,我构建了这个答案,同时牢记以下内容:
Array.prototype.filter
或Array.prototype.sort
。eval
(或Function
)不应在每次拨打comparator
时使用
答案 1 :(得分:2)
不要动态地这样做......只创建一次函数,而不是每次调用它们会更有效率,因为这会创建一个新的函数,因此每次都会发生内存泄漏比较完成。
var comparator = {
">=": function(a, b) { return a >= b;},
"<=": function(a, b) { return a <= b;},
"add": function(a, b) { return a + b; },
compare: function(typeString, a, b){
if(comparator.hasOwnProperty(typeString) == true){
var theFunction = comparator[typeString];
return theFunction(a, b);
}
else{
alert("typeString '" + typeString + "' not supported.");
}
}, };
var test = comparator.compare(">=", 5, 4);
答案 2 :(得分:2)
var comparator = (function () {
var fns = {
'>=': function (a, c) { return a >= c; },
'<=': function (a, c) { return a <= c; },
'<': function (a, c) { return a < c; },
'>': function (a, c) { return a > c; },
'=': function (a, c) { return a == c; },
'==': function (a, c) { return a === c; },
'!=': function (a, c) { return a != c; }
};
return function (b) {
return fns.hasOwnProperty(b) ? fns[b] : null;
};
}());
此时您可以看到没有什么比内联表达式更有效。我不清楚为什么你认为你需要事先变得如此有活力。