diff --git a/README.md b/README.md index 1e89449..d9142df 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,13 @@ var count = normalize('number', function(a, b) { }, 1, 2); // count === 3 +// Bind the function to supply it with context +var context = { c: 3 }; +var count = normalize.bind(context)('number', function(a, b) { + return a + b + this.c; +}, 1, 2); +// count === 6 + // Values one of multiple types are returned var isEnabled = normalize(['string', 'boolean'], true); // isEnabled === true diff --git a/index.js b/index.js index 0002f70..2390f99 100644 --- a/index.js +++ b/index.js @@ -18,13 +18,13 @@ function normalize(coercer, value) { if (coercer === 'function') { return value; } - value = value.apply(null, Array.prototype.slice.call(arguments, 2)); + value = value.apply(this, Array.prototype.slice.call(arguments, 2)); } - return coerce(coercer, value); + return coerce(this, coercer, value); } -function coerce(coercer, value) { +function coerce(context, coercer, value) { // Handle built-in types if (typeof coercer === 'string') { @@ -36,13 +36,13 @@ function coerce(coercer, value) { // Handle custom coercer if (typeof coercer === 'function') { - return coercer(value); + return coercer.call(context, value); } // Array of coercers, try in order until one returns a non-null value var result = null; coercer.some(function(coercer) { - result = coerce(coercer, value); + result = coerce(context, coercer, value); return result !== null; }); @@ -99,10 +99,17 @@ function primitive(value) { } -// Add methods for each type -types.forEach(function(type) { - normalize[type] = normalize.bind(null, type); -}); +function bind(context) { + var fun = Function.prototype.bind.call(normalize, context); + fun.bind = bind; + + // Add methods for each type + types.forEach(function(type) { + fun[type] = Function.prototype.bind.call(normalize, context, type); + }); + + return fun; +} -module.exports = normalize; +module.exports = bind(null); diff --git a/test/index.js b/test/index.js index 59d84a1..abf6816 100644 --- a/test/index.js +++ b/test/index.js @@ -46,17 +46,17 @@ describe('normalize', function() { done(); }); - it('supports functions for the type parameter', function(done) { + it('supports coercer functions for the type parameter', function(done) { var type = function() { return true; }; var value = 1; var result = normalize(type, value); - expect(result).toEqual(value); + expect(result).toBe(true); done(); }); - it('calls the type function to attempt coercion', function(done) { + it('calls the coercer function to attempt coercion', function(done) { var expected = 1; var type = expect.createSpy().andCall(function(value) { return value; @@ -67,6 +67,19 @@ describe('normalize', function() { done(); }); + it('calls the coercer functions with context, if bound', function(done) { + var expected = 1; + var context = {}; + var type = expect.createSpy().andCall(function(value) { + expect(this).toBe(context); + return value; + }); + var result = normalize.bind(context)(type, expected); + expect(result).toEqual(expected); + expect(type).toHaveBeenCalled(); + done(); + }); + it('calls the value if it is a function', function(done) { var type = 'string'; var expected = 'test string'; @@ -79,6 +92,17 @@ describe('normalize', function() { done(); }); + it('calls the value function with context, if bound', function(done) { + var type = 'string'; + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context)(type, value); + expect(value).toHaveBeenCalled(); + done(); + }); + it('checks the result of function against coercer', function(done) { var expected = 'test string'; var coercer = expect.createSpy().andCall(function(value) { @@ -163,6 +187,16 @@ describe('normalize.object', function() { expect(result).toEqual(null); done(); }); + + it('calls the object function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context).object(value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.number', function() { @@ -202,6 +236,16 @@ describe('normalize.number', function() { expect(result).toEqual(null); done(); }); + + it('calls the number function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context).number(value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.string', function() { @@ -250,6 +294,16 @@ describe('normalize.string', function() { expect(result).toEqual(null); done(); }); + + it('calls the string function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context).string(value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.symbol', function() { @@ -278,6 +332,21 @@ describe('normalize.symbol', function() { expect(result).toEqual(null); done(); }); + + it('calls the symbol function with context, if bound', function(done) { + if (!global.Symbol) { + console.log('Only available on platforms that support Symbol'); + this.skip(); + return; + } + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context).symbol(value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.boolean', function() { @@ -303,6 +372,16 @@ describe('normalize.boolean', function() { expect(result).toEqual(null); done(); }); + + it('calls the boolean function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context).boolean(value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.function', function() { @@ -345,6 +424,16 @@ describe('normalize.undefined', function() { expect(result).toEqual(null); done(); }); + + it('calls the undefined function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context).undefined(value); + expect(value).toHaveBeenCalled(); + done(); + }); }); describe('normalize.date', function() { @@ -413,4 +502,14 @@ describe('normalize.date', function() { expect(result).toEqual(null); done(); }); + + it('calls the date function with context, if bound', function(done) { + var context = {}; + var value = expect.createSpy().andCall(function() { + expect(this).toBe(context); + }); + normalize.bind(context).date(value); + expect(value).toHaveBeenCalled(); + done(); + }); });