[question] Decorator
#
function Decorator(options) { if (!options) { options = {}; } this.before = options.before; this.after = options.after; } Decorator.prototype.decorate = function decorate(fn) { var decArgs = Array.prototype.slice.call(arguments, 1), self = this; return function() { var input = Array.prototype.slice.call(arguments, 0); if(typeof self.before == 'function') { input = self.before.apply(null, decArgs.concat(input)) || input; } input = fn.apply(self, input); if(typeof self.after == 'function') { input = self.after.apply(null, decArgs.concat(input)) || input; } return input; } };
#
function sum() { return Array.prototype.reduce.call(arguments, function(sum, value) { return sum + value; }, 0); } function filter(min, max) { return Array.prototype.slice.call(arguments, 2).filter(function(value) { return value >= min && value <= max; }); } function filterNoNumbers() { return Array.prototype.filter.call(arguments, function(value) { return typeof value === 'number' && value === value && value !== Number.POSITIVE_INFINITY && value !== Number.NEGATIVE_INFINITY; }); } function round(decimals) { if (arguments.length === 2) { return arguments[1].toFixed(decimals); } else { return Array.prototype.splice.call(arguments, 1).map(function(value) { return value.toFixed(decimals); }); } } var nullDecorator = new Decorator(); var testNullDecorator = nullDecorator.decorate(function() { return true; }); Test.assertEquals(testNullDecorator(), true, 'A null decorator does nothing'); var filterDecorator = new Decorator({ before : filter }); var decoratedSum = filterDecorator.decorate(sum, 1, 9); Test.assertSimilar(decoratedSum(-3, 1, 0, 4, 8, 9, 12), 22, 'sum values that are between the minimum and maximum'); var filterNoNumbersDecorator = new Decorator({ before : filterNoNumbers }); decoratedSum = filterNoNumbersDecorator.decorate(decoratedSum); Test.assertEquals(decoratedSum(-3, 1, 0, 4, NaN, 8, '27', 9, 12), 22, 'sum values that are numbers and are between the minimum and maximum'); var roundDecorator = new Decorator({ after: round }); decoratedSum = roundDecorator.decorate(decoratedSum, 2); Test.assertEquals(decoratedSum(-3, 1.016, 0, 4, NaN, 8.041, '27', 9, 12), "22.06", 'sum isRounded to two decimals'); decoratedSum = nullDecorator.decorate(decoratedSum, 2); Test.assertEquals(decoratedSum(-3, 1.016, 0, 4, NaN, 8.041, '27', 9, 12), "22.06", 'A null decorator does nothing'); var decoratedSum2 = filterNoNumbersDecorator.decorate(sum); decoratedSum2 = roundDecorator.decorate(decoratedSum2, 2); decoratedSum2 = filterDecorator.decorate(decoratedSum2, 1, 9); Test.assertEquals(decoratedSum2(-3, 1.016, 0, 4, NaN, 8.041, '27', 9, 12), "22.06", 'The order in which decorators are applied does not alter the result.');
浙公网安备 33010602011771号