Вот решение, которое я нашел (если кому понадобится в будущем):
/**
* @param {Array} settings.arr
* @param {Number} settings.valueToFind
* @param {Function} settings.comparator
*
* @returns {Number|undefined}
*/
function findClosest(settings) {
var lo = -Infinity,
hi = Infinity,
arr = settings.arr,
valueToFind = settings.valueToFind,
comparator = settings.comparator,
result;
for (var i = 0; i < arr.length; i++) {
if (arr[i] <= valueToFind && arr[i] >= lo) {
lo = arr[i];
continue;
}
if (arr[i] >= valueToFind && arr[i] <= hi) {
hi = arr[i];
}
}
result = comparator(lo, hi, valueToFind);
return isFinite(result) ? result : undefined; // or false
}
Вот так выглядит объект settings c четырьмя возможными компараторами:
var comparator1 = function(lo, hi, valueToFind) {
return lo; // or hi
};
var comparator2 = function(lo, hi, valueToFind) {
var result = lo; // or hi
switch (true) {
case valueToFind - lo < hi - valueToFind:
result = lo;
break;
case valueToFind - lo > hi - valueToFind:
result = hi;
break;
}
return result;
};
var settings = {
arr: [1, 5, 10, 8, 5, 13],
valueToFind: 7,
comparator: comparator2
};
И сам вызов функции:
alert(findClosest(settings));
PS:
Вместо false, в случае когда результат не определен, я решил возвращать undefined, так как это значение ближе по семантике.