├── src ├── helper.js ├── apply.js ├── delay.js ├── toArray.js ├── is.js ├── prop.js ├── reverse.js ├── concat.js ├── compose.js ├── flip.js ├── filter.js ├── properties.js ├── delayed.js ├── type.js ├── each.js ├── reduce.js ├── map.js ├── partial.js ├── pipeline.js ├── memoize.js ├── merge.js ├── throttle.js ├── debounce.js └── curry.js ├── README.md ├── .gitignore ├── tests ├── delay.js ├── delayFor.js ├── properties.js ├── flip.js ├── delayed.js ├── delayedFor.js ├── curry.js ├── cloneArray.js ├── apply.js ├── toArray.js ├── async.js ├── throttle.js ├── debounce.js ├── compose.js ├── filter.js ├── partial.js ├── pipeline.js ├── prop.js ├── reverse.js ├── map.js ├── concat.js ├── merge.js ├── reduce.js ├── each.js ├── memoize.js ├── op.js └── is.js ├── package.json ├── Gruntfile.js ├── LICENSE └── .jshintrc /src/helper.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fn.js 2 | 3 | fn.js is a JavaScript library built to encourage a functional programming style & strategy. 4 | 5 | -------------------------------------------------------------------------------- /src/apply.js: -------------------------------------------------------------------------------- 1 | // fn.apply 2 | module.exports = function (handler, args) { 3 | 'use strict'; 4 | return handler.apply(null, args); 5 | }; -------------------------------------------------------------------------------- /src/delay.js: -------------------------------------------------------------------------------- 1 | // fn.delay 2 | module.exports = function (handler, msDelay) { 3 | 'use strict'; 4 | return setTimeout(handler, msDelay); 5 | }; -------------------------------------------------------------------------------- /src/toArray.js: -------------------------------------------------------------------------------- 1 | // fn.toArray 2 | module.exports = function (collection) { 3 | 'use strict'; 4 | return [].slice.call(collection); 5 | }; -------------------------------------------------------------------------------- /src/is.js: -------------------------------------------------------------------------------- 1 | var fnType = require('./type.js'); 2 | // fn.is 3 | module.exports = function (type, value) { 4 | 'use strict'; 5 | return type === fnType(value); 6 | }; -------------------------------------------------------------------------------- /src/prop.js: -------------------------------------------------------------------------------- 1 | var fnCurry = require('./curry'); 2 | // fn.prop 3 | module.exports = fnCurry(function (name, object) { 4 | 'use strict'; 5 | return object[name]; 6 | }); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | .idea/ 16 | node_modules/ -------------------------------------------------------------------------------- /src/reverse.js: -------------------------------------------------------------------------------- 1 | var fnCloneArray = require('./toArray'); 2 | // fn.reverse 3 | module.exports = function (collection) { 4 | 'use strict'; 5 | return fnCloneArray(collection).reverse(); 6 | }; -------------------------------------------------------------------------------- /src/concat.js: -------------------------------------------------------------------------------- 1 | var fnToArray = require('./toArray'); 2 | 3 | // fn.concat 4 | module.exports = function () { 5 | 'use strict'; 6 | var args = fnToArray(arguments); 7 | 8 | return args[0].concat.apply(args[0], args.slice(1)); 9 | }; -------------------------------------------------------------------------------- /src/compose.js: -------------------------------------------------------------------------------- 1 | var fnApply = require('./apply'); 2 | var fnPipeline = require('./pipeline'); 3 | var fnReverse = require('./reverse'); 4 | // fn.compose 5 | module.exports = function () { 6 | 'use strict'; 7 | return fnApply(fnPipeline, fnReverse(arguments)); 8 | }; -------------------------------------------------------------------------------- /src/flip.js: -------------------------------------------------------------------------------- 1 | var fnApply = require('./apply'); 2 | var fnReverse = require('./reverse'); 3 | // fn.flip 4 | module.exports = function (handler) { 5 | 'use strict'; 6 | return function () { 7 | return fnApply(handler, fnReverse(arguments)); 8 | }; 9 | }; -------------------------------------------------------------------------------- /src/filter.js: -------------------------------------------------------------------------------- 1 | var fnReduce = require('./reduce'); 2 | // fn.filter 3 | module.exports = function (expression, collection) { 4 | 'use strict'; 5 | return fnReduce(function (accumulator, item, index) { 6 | expression(item, index) && accumulator.push(item); 7 | return accumulator; 8 | }, [], collection); 9 | }; -------------------------------------------------------------------------------- /src/properties.js: -------------------------------------------------------------------------------- 1 | // fn.properties 2 | module.exports = function (object) { 3 | 'use strict'; 4 | var accumulator = []; 5 | 6 | for (var property in object) { 7 | if (object.hasOwnProperty(property)) { 8 | accumulator.push(property); 9 | } 10 | } 11 | 12 | return accumulator; 13 | }; -------------------------------------------------------------------------------- /src/delayed.js: -------------------------------------------------------------------------------- 1 | var fnDelay = require('./delay'); 2 | var fnPartial = require('./partial'); 3 | var fnToArray = require('./toArray'); 4 | // fn.delayed 5 | module.exports = function (handler, msDelay) { 6 | 'use strict'; 7 | return function () { 8 | return fnDelay(fnPartial(handler, fnToArray(arguments)), msDelay); 9 | }; 10 | }; -------------------------------------------------------------------------------- /src/type.js: -------------------------------------------------------------------------------- 1 | // fn.type 2 | module.exports = function (value) { 3 | 'use strict'; 4 | // If the value is null or undefined, return the stringified name, 5 | // otherwise get the [[Class]] and compare to the relevant part of the value 6 | return value == null ? 7 | '' + value : 8 | ({}).toString.call(value).slice(8, -1).toLowerCase(); 9 | }; -------------------------------------------------------------------------------- /src/each.js: -------------------------------------------------------------------------------- 1 | var fnApply = require('./apply'); 2 | var fnConcat = require('./concat'); 3 | // fn.each 4 | module.exports = function (handler, collection, params) { 5 | 'use strict'; 6 | for (var index = 0, collectionLength = collection.length; index < collectionLength; index++) { 7 | fnApply(handler, fnConcat([collection[index], index, collection], params)); 8 | } 9 | }; -------------------------------------------------------------------------------- /tests/delay.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.delay()', function () { 6 | 7 | it('should delay the execution of the handler to at least the duration provided', function (done) { 8 | var then = Date.now(); 9 | 10 | fn.delay(function () { 11 | expect(Date.now() - then).to.be.at.least(48); 12 | done(); 13 | }, 50); 14 | }); 15 | 16 | }); -------------------------------------------------------------------------------- /src/reduce.js: -------------------------------------------------------------------------------- 1 | var fnEach = require('./each'); 2 | var fnApply = require('./apply'); 3 | var fnConcat = require('./concat'); 4 | 5 | // fn.reduce 6 | module.exports = function (handler, accumulator, collection, params) { 7 | 'use strict'; 8 | fnEach(function (value, index) { 9 | accumulator = fnApply(handler, fnConcat([accumulator, value, index], params)); 10 | }, collection); 11 | 12 | return accumulator; 13 | }; -------------------------------------------------------------------------------- /src/map.js: -------------------------------------------------------------------------------- 1 | var fnReduce = require('./reduce'); 2 | var fnApply = require('./apply'); 3 | var fnConcat = require('./concat'); 4 | // fn.map 5 | module.exports = function (handler, collection, params) { 6 | 'use strict'; 7 | return fnReduce(function (accumulator, value, index) { 8 | accumulator.push(fnApply(handler, fnConcat([value, index, collection], params))); 9 | return accumulator; 10 | }, [], collection); 11 | }; -------------------------------------------------------------------------------- /tests/delayFor.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.delayFor()', function () { 6 | 7 | it('should delay the execution of the handler to at least the duration provided', function (done) { 8 | var then = Date.now(); 9 | 10 | fn.delayFor(50, function () { 11 | expect(Date.now() - then).to.be.at.least(48); 12 | done(); 13 | }); 14 | }); 15 | 16 | }); -------------------------------------------------------------------------------- /src/partial.js: -------------------------------------------------------------------------------- 1 | var fnToArray = require('./toArray'); 2 | var fnApply = require('./apply'); 3 | var fnConcat = require('./concat'); 4 | // fn.partial 5 | module.exports = function () { 6 | 'use strict'; 7 | var args = fnToArray(arguments); 8 | var handler = args[0]; 9 | var partialArgs = args.slice(1); 10 | 11 | return function () { 12 | return fnApply(handler, fnConcat(partialArgs, fnToArray(arguments)) ); 13 | }; 14 | }; -------------------------------------------------------------------------------- /src/pipeline.js: -------------------------------------------------------------------------------- 1 | var fnToArray = require('./toArray'); 2 | var fnReduce = require('./reduce'); 3 | var fnApply = require('./apply'); 4 | // fn.pipeline 5 | module.exports = function () { 6 | 'use strict'; 7 | var functions = fnToArray(arguments); 8 | 9 | return function () { 10 | return fnReduce(function (args, func) { 11 | return [fnApply(func, args)]; 12 | }, fnToArray(arguments), functions)[0]; 13 | }; 14 | }; -------------------------------------------------------------------------------- /tests/properties.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.properties()', function () { 6 | 7 | it('should extract all own properties of an object', function () { 8 | var obj = { 9 | a: 1, 10 | b: 2, 11 | c: 3 12 | }; 13 | 14 | var properties = fn.properties(obj); 15 | 16 | expect(properties).to.have.length(3); 17 | expect(properties).to.have.members(['a', 'b', 'c']); 18 | }); 19 | 20 | }); -------------------------------------------------------------------------------- /tests/flip.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.flip()', function () { 6 | 7 | it('should reverse the order of argument application', function () { 8 | var echo = fn.flip(function (a, b, c) { 9 | return [a, b, c]; 10 | }); 11 | 12 | var values = echo(1, 2, 3); 13 | 14 | expect(values[0]).to.equal(3); 15 | expect(values[1]).to.equal(2); 16 | expect(values[2]).to.equal(1); 17 | }); 18 | 19 | }); -------------------------------------------------------------------------------- /tests/delayed.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.delayed()', function () { 6 | 7 | it('should return a new function that when invoked, delays evaluation for a specified duration', function (done) { 8 | var then = Date.now(); 9 | 10 | var delayedTime = fn.delayed(function () { 11 | expect(Date.now() - then).to.be.at.least(48); 12 | done(); 13 | }, 50); 14 | 15 | delayedTime(1, 2, 3); 16 | }); 17 | 18 | }); -------------------------------------------------------------------------------- /tests/delayedFor.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.delayedFor()', function () { 6 | 7 | it('should return a new function that when invoked, delays evaluation for a specified duration', function (done) { 8 | var then = Date.now(); 9 | 10 | var delayedTime = fn.delayedFor(50, function () { 11 | expect(Date.now() - then).to.be.at.least(48); 12 | done(); 13 | }); 14 | 15 | delayedTime(); 16 | }); 17 | 18 | }); -------------------------------------------------------------------------------- /src/memoize.js: -------------------------------------------------------------------------------- 1 | var fnToArray = require('./toArray'); 2 | var fnApply = require('./apply'); 3 | // fn.memoize 4 | module.exports = function memoize(handler, serializer) { 5 | 'use strict'; 6 | var cache = {}; 7 | 8 | return function () { 9 | var args = fnToArray(arguments); 10 | var key = serializer ? serializer(args) : memoize.serialize(args); 11 | 12 | return key in cache ? 13 | cache[key] : 14 | cache[key] = fnApply(handler, args); 15 | }; 16 | }; -------------------------------------------------------------------------------- /tests/curry.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.curry()', function () { 6 | 7 | it('should recursively apply arguments to a function', function () { 8 | var add = fn.curry(function (a, b, c) { 9 | return a + b + c; 10 | }); 11 | 12 | var add37 = add(37); 13 | 14 | expect(add37(2, 3)).to.equal(42); 15 | expect(add37(5)(9)).to.equal(51); 16 | expect(add37(10)()()()()()()(20)).to.equal(67); 17 | }); 18 | 19 | }); -------------------------------------------------------------------------------- /src/merge.js: -------------------------------------------------------------------------------- 1 | var fnReduce = require('./reduce'); 2 | var fnEach = require('./each'); 3 | var fnProperties = require('./properties'); 4 | var fnToArray = require('./toArray'); 5 | // fn.merge 6 | module.exports = function () { 7 | 'use strict'; 8 | return fnReduce(function (accumulator, value) { 9 | fnEach(function (property) { 10 | accumulator[property] = value[property]; 11 | }, fnProperties(value)); 12 | 13 | return accumulator; 14 | }, {}, fnToArray(arguments)); 15 | }; -------------------------------------------------------------------------------- /tests/cloneArray.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.cloneArray()', function () { 6 | 7 | it('should clone an array', function () { 8 | var arr = [ 1, 'string', true ]; 9 | var clone = fn.cloneArray(arr); 10 | 11 | expect(arr).to.not.equal(clone); 12 | expect(clone).to.not.equal(arr); 13 | expect(arr[0]).to.equal(clone[0]); 14 | expect(arr[1]).to.equal(clone[1]); 15 | expect(arr[2]).to.equal(clone[2]); 16 | }); 17 | 18 | }); -------------------------------------------------------------------------------- /tests/apply.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.apply()', function () { 6 | 7 | var args = [ 1, 'string', true ]; 8 | var func = function (a, b, c) { 9 | return [ a, b, c ]; 10 | }; 11 | 12 | it('should apply arguments to a function', function () { 13 | var result = fn.apply(func, args); 14 | 15 | expect(result[0]).to.equal(1); 16 | expect(result[1]).to.equal('string'); 17 | expect(result[2]).to.equal(true); 18 | }); 19 | 20 | }); -------------------------------------------------------------------------------- /tests/toArray.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.toArray()', function () { 6 | 7 | var func = function () { 8 | return arguments; 9 | }; 10 | 11 | it('should convert arguments to an array', function () { 12 | var result = fn.toArray( func(1, 'string', true) ); 13 | 14 | expect( fn.is(result, 'array')).to.be.true; 15 | expect(result[0]).to.equal(1); 16 | expect(result[1]).to.equal('string'); 17 | expect(result[2]).to.equal(true); 18 | }); 19 | 20 | }); -------------------------------------------------------------------------------- /tests/async.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.async()', function () { 6 | 7 | it('should return a new function that is always invoked at the end of the event loop', function (done) { 8 | var value = 10; 9 | 10 | var changeValue = fn.async(function () { 11 | value = 20; 12 | }); 13 | 14 | changeValue(); 15 | expect(value).to.equal(10); 16 | 17 | setTimeout(function () { 18 | expect(value).to.equal(20); 19 | done(); 20 | }, 50) 21 | }); 22 | 23 | }); -------------------------------------------------------------------------------- /src/throttle.js: -------------------------------------------------------------------------------- 1 | var fnToArray = require('./toArray'); 2 | var fnDelay = require('./delay'); 3 | var fnApply = require('./apply'); 4 | 5 | // fn.throttle 6 | module.exports = function (handler, msDelay) { 7 | 'use strict'; 8 | var throttling; 9 | 10 | return function () { 11 | var args = fnToArray(arguments); 12 | 13 | if (throttling) { 14 | return; 15 | } 16 | 17 | throttling = fnDelay(function () { 18 | throttling = false; 19 | 20 | fnApply(handler, args); 21 | }, msDelay); 22 | }; 23 | }; -------------------------------------------------------------------------------- /tests/throttle.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.throttle()', function () { 6 | 7 | it('should only allow a certain number of executions in a timeframe', function (done) { 8 | var iterations = 0; 9 | 10 | var increment = fn.throttle(function () { 11 | iterations++; 12 | }, 50); 13 | 14 | var interval = setInterval(increment, 10); 15 | 16 | fn.delay(function () { 17 | expect(iterations).to.be.at.most(10); 18 | clearInterval(interval); 19 | done(); 20 | }, 500); 21 | }); 22 | 23 | }); -------------------------------------------------------------------------------- /src/debounce.js: -------------------------------------------------------------------------------- 1 | var fnToArray = require('./toArray'); 2 | var fnDelay = require('./delay'); 3 | var fnApply = require('./apply'); 4 | 5 | // fn.debounce 6 | module.exports = function (handler, msDelay) { 7 | 'use strict'; 8 | var debouncing; 9 | 10 | return function () { 11 | var args = fnToArray(arguments); 12 | 13 | if (debouncing) { 14 | clearTimeout(debouncing); 15 | } 16 | 17 | debouncing = fnDelay(function () { 18 | debouncing = false; 19 | 20 | fnApply(handler, args); 21 | }, msDelay); 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /tests/debounce.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.debounce()', function () { 6 | 7 | it('should only allow one execution in a timeframe', function (done) { 8 | var iterations = 0; 9 | 10 | var increment = fn.debounce(function () { 11 | iterations++; 12 | }, 50); 13 | 14 | var interval = setInterval(increment, 10); 15 | 16 | fn.delay(function () { 17 | clearInterval(interval); 18 | 19 | fn.delay(function () { 20 | expect(iterations).to.equal(1); 21 | done(); 22 | }, 100); 23 | }, 250); 24 | }); 25 | 26 | }); -------------------------------------------------------------------------------- /tests/compose.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.compose()', function () { 6 | 7 | var func = null; 8 | 9 | beforeEach(function() { 10 | func = fn.compose( 11 | fn.partial( fn.op['+'], 3 ), 12 | fn.partial( fn.op['*'], 6 ), 13 | function (num) { 14 | return Math.pow(num, 2); 15 | }); 16 | }); 17 | 18 | it('should return a new function', function () { 19 | expect(func).to.be.a('function'); 20 | }); 21 | 22 | it('should pass return values from right to left', function () { 23 | var result = func(7); 24 | 25 | expect(result).to.equal(297); 26 | }); 27 | 28 | }); -------------------------------------------------------------------------------- /tests/filter.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.filter()', function () { 6 | 7 | it('should reduce the elements of an array based on an evaluating expression', function () { 8 | var collection = [1, 'string', true, undefined, [], {}, NaN]; 9 | 10 | var result = fn.filter(function (value) { 11 | return !!value; 12 | }, collection); 13 | 14 | expect(result).to.have.length(5); 15 | expect(result[0]).to.equal(1); 16 | expect(result[1]).to.equal('string'); 17 | expect(result[2]).to.be.true; 18 | expect(result[3]).to.be.an('array'); 19 | expect(result[4]).to.be.an('object'); 20 | }); 21 | 22 | }); -------------------------------------------------------------------------------- /tests/partial.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.partial()', function () { 6 | 7 | it('should partially apply arguments to a function', function () { 8 | var func = function (a, b, c, d, e) { 9 | return [ a, b, c, d, e ]; 10 | }; 11 | 12 | var partialFunc = fn.partial(func, 1, 'string', true); 13 | var result = partialFunc(3, false); 14 | 15 | expect(result.length).to.equal(5); 16 | expect(result[0]).to.equal(1); 17 | expect(result[1]).to.equal('string'); 18 | expect(result[2]).to.equal(true); 19 | expect(result[3]).to.equal(3); 20 | expect(result[4]).to.equal(false); 21 | }); 22 | 23 | }); -------------------------------------------------------------------------------- /src/curry.js: -------------------------------------------------------------------------------- 1 | var fnToArray = require('./toArray'); 2 | // fn.curry 3 | module.exports = function (handler, arity) { 4 | 'use strict'; 5 | if (handler.curried) { 6 | return handler; 7 | } 8 | 9 | arity = arity || handler.length; 10 | 11 | var curry = function curry() { 12 | var args = fnToArray(arguments); 13 | 14 | if (args.length >= arity) { 15 | return handler.apply(null, args); 16 | } 17 | 18 | var inner = function () { 19 | return curry.apply(null, args.concat(fnToArray(arguments))); 20 | }; 21 | 22 | inner.curried = true; 23 | 24 | return inner; 25 | }; 26 | 27 | curry.curried = true; 28 | 29 | return curry; 30 | }; -------------------------------------------------------------------------------- /tests/pipeline.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.pipeline()', function () { 6 | 7 | it('should return a new function', function () { 8 | 9 | var func = fn.pipeline( 10 | fn.partial( fn.op['+'], 3 ), 11 | fn.partial( fn.op['*'], 6 ), 12 | function (num) { 13 | return Math.pow(num, 2); 14 | }); 15 | 16 | expect(func).to.be.a('function'); 17 | }); 18 | 19 | it('should pass return values from left to right', function () { 20 | var func = fn.pipeline( 21 | fn.partial( fn.op['+'], 3 ), 22 | fn.partial( fn.op['*'], 6 ), 23 | function (num) { 24 | return Math.pow(num, 2); 25 | }); 26 | 27 | var result = func(7); 28 | 29 | expect(result).to.equal(3600); 30 | }); 31 | 32 | }); -------------------------------------------------------------------------------- /tests/prop.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.prop()', function () { 6 | 7 | it('should extract a value from an object by property name', function () { 8 | var obj = { 9 | a: 1, 10 | b: 2, 11 | c: 3 12 | }; 13 | 14 | expect(fn.prop('a', obj)).to.equal(1); 15 | expect(fn.prop('b', obj)).to.equal(2); 16 | expect(fn.prop('c', obj)).to.equal(3); 17 | }); 18 | 19 | it('should curry properties until object is received', function () { 20 | var obj1 = { 21 | a: 1 22 | }; 23 | 24 | var obj2 = { 25 | a: 10 26 | }; 27 | 28 | var obj3 = { 29 | a: 100 30 | }; 31 | 32 | var getA = fn.prop('a'); 33 | 34 | expect(getA(obj1)).to.equal(1); 35 | expect(getA(obj2)).to.equal(10); 36 | expect(getA(obj3)).to.equal(100); 37 | }); 38 | 39 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fn.js", 3 | "version": "0.7.0", 4 | "description": "Functional programming strategy library for JavaScript", 5 | "main": "build/fn.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/eliperelman/fn.js" 9 | }, 10 | "keywords": [ 11 | "functional", 12 | "programming", 13 | "fp" 14 | ], 15 | "author": "Eli Perelman", 16 | "homepage": "https://github.com/eliperelman/fn.js", 17 | "license": "MIT", 18 | "gitHead": "03ee04cb590f1692f60737c576ff50e43e1ea943", 19 | "readmeFilename": "README.md", 20 | "bugs": { 21 | "url": "https://github.com/eliperelman/fn.js/issues" 22 | }, 23 | "devDependencies": { 24 | "grunt": "~0.4.1", 25 | "grunt-bump": "0.0.11", 26 | "grunt-umd": "~1.1.0", 27 | "grunt-contrib-jshint": "~0.6.2", 28 | "grunt-cafe-mocha": "~0.1.8", 29 | "chai": "~1.7.2" 30 | }, 31 | "dependencies": {} 32 | } 33 | -------------------------------------------------------------------------------- /tests/reverse.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.reverse()', function () { 6 | 7 | it('should contain an array of reversed values', function () { 8 | var values = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; 9 | 10 | var result = fn.reverse(values); 11 | 12 | expect(result).to.have.length(9); 13 | expect(result[0]).to.equal(9); 14 | expect(result[1]).to.equal(8); 15 | expect(result[2]).to.equal(7); 16 | expect(result[3]).to.equal(6); 17 | expect(result[4]).to.equal(5); 18 | expect(result[5]).to.equal(4); 19 | expect(result[6]).to.equal(3); 20 | expect(result[7]).to.equal(2); 21 | expect(result[8]).to.equal(1); 22 | }); 23 | 24 | it('should not be the same array', function () { 25 | var values = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; 26 | 27 | var result = fn.reverse(values); 28 | 29 | expect(result).to.not.equal(values); 30 | }); 31 | 32 | }); -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 3 | grunt.initConfig({ 4 | bump: { 5 | options: { 6 | commit: true, 7 | createTag: true, 8 | push: true, 9 | pushTo: 'origin' 10 | } 11 | }, 12 | umd: { 13 | main: { 14 | src: 'src/index.js', 15 | dest: 'build/fn.js', 16 | objectToExport: 'fn', 17 | globalAlias: 'fn', 18 | deps: {} 19 | } 20 | }, 21 | jshint: { 22 | main: { 23 | files: { 24 | src: ['src/**/*.js'] 25 | }, 26 | options: { 27 | jshintrc: '.jshintrc' 28 | } 29 | } 30 | }, 31 | cafemocha: { 32 | main: { 33 | src: 'tests/**/*.js', 34 | options: { 35 | ui: 'tdd', 36 | reporter: 'spec', 37 | require: [ 38 | 'chai' 39 | ] 40 | } 41 | } 42 | } 43 | }); 44 | 45 | grunt.registerTask('default', ['jshint:main', 'umd:main', 'cafemocha:main']); 46 | 47 | grunt.loadNpmTasks('grunt-bump'); 48 | grunt.loadNpmTasks('grunt-umd'); 49 | grunt.loadNpmTasks('grunt-contrib-jshint'); 50 | grunt.loadNpmTasks('grunt-cafe-mocha'); 51 | }; -------------------------------------------------------------------------------- /tests/map.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.map()', function () { 6 | 7 | it('should return a new array of values', function () { 8 | var values = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; 9 | 10 | var result = fn.map(function (value) { 11 | return value * 2; 12 | }, values); 13 | 14 | expect(result).to.have.length(9); 15 | expect(result[0]).to.equal(2); 16 | expect(result[1]).to.equal(4); 17 | expect(result[2]).to.equal(6); 18 | expect(result[3]).to.equal(8); 19 | expect(result[4]).to.equal(10); 20 | expect(result[5]).to.equal(12); 21 | expect(result[6]).to.equal(14); 22 | expect(result[7]).to.equal(16); 23 | expect(result[8]).to.equal(18); 24 | }); 25 | 26 | it('should receive an index', function () { 27 | var values = [ 1, 2, 3 ]; 28 | 29 | var result = fn.map(function (value, index) { 30 | return index; 31 | }, values); 32 | 33 | expect(result).to.have.length(3); 34 | expect(result[0]).to.equal(0); 35 | expect(result[1]).to.equal(1); 36 | expect(result[2]).to.equal(2); 37 | }); 38 | 39 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Eli Perelman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "camelcase": true, 4 | "curly": true, 5 | "eqeqeq": false, 6 | "es3": false, 7 | "forin": true, 8 | "immed": true, 9 | "indent": 4, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "noempty": true, 14 | "nonew": false, 15 | "plusplus": false, 16 | "quotmark": true, 17 | "undef": true, 18 | "unused": true, 19 | "strict": true, 20 | "trailing": true, 21 | "maxparams": 4, 22 | "maxdepth": 3, 23 | "maxlen": 120, 24 | "asi": false, 25 | "boss": false, 26 | "debug": false, 27 | "eqnull": true, 28 | "esnext": false, 29 | "evil": false, 30 | "expr": true, 31 | "funcscope": false, 32 | "globalstrict": false, 33 | "iterator": false, 34 | "lastsemic": false, 35 | "laxbreak": false, 36 | "laxcomma": false, 37 | "loopfunc": false, 38 | "moz": false, 39 | "multistr": false, 40 | "proto": false, 41 | "scripturl": false, 42 | "smarttabs": false, 43 | "shadow": false, 44 | "sub": false, 45 | "supernew": false, 46 | "validthis": false, 47 | "browser": true, 48 | "couch": false, 49 | "devel": true, 50 | "dojo": false, 51 | "jquery": false, 52 | "mootools": false, 53 | "node": true, 54 | "nonstandard": false, 55 | "phantom": false, 56 | "prototypejs": false, 57 | "rhino": false, 58 | "worker": false, 59 | "wsh": false, 60 | "yui": false, 61 | "nomen": false, 62 | "onevar": false, 63 | "passfail": false, 64 | "white": false 65 | } -------------------------------------------------------------------------------- /tests/concat.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.concat()', function () { 6 | 7 | it('should combine two arrays into one', function () { 8 | var arr1 = [ 1, 'string', true ]; 9 | var arr2 = [ 2, 'newstring', false ]; 10 | 11 | var result = fn.concat(arr1, arr2); 12 | 13 | expect(result).to.have.length(6); 14 | expect(result).to.not.equal(arr1); 15 | expect(result).to.not.equal(arr2); 16 | expect(result[0]).to.equal(1); 17 | expect(result[1]).to.equal('string'); 18 | expect(result[2]).to.equal(true); 19 | expect(result[3]).to.equal(2); 20 | expect(result[4]).to.equal('newstring'); 21 | expect(result[5]).to.equal(false); 22 | }); 23 | 24 | it('should combine three arrays into one', function () { 25 | var arr1 = [ 1, 'string', true ]; 26 | var arr2 = [ 2, 'newstring', false ]; 27 | var arr3 = [ 3, 'laststring', true ]; 28 | 29 | var result = fn.concat(arr1, arr2, arr3); 30 | 31 | 32 | expect(result).to.have.length(9); 33 | expect(result).to.not.equal(arr1); 34 | expect(result).to.not.equal(arr2); 35 | expect(result).to.not.equal(arr3); 36 | expect(result[0]).to.equal(1); 37 | expect(result[1]).to.equal('string'); 38 | expect(result[2]).to.equal(true); 39 | expect(result[3]).to.equal(2); 40 | expect(result[4]).to.equal('newstring'); 41 | expect(result[5]).to.equal(false); 42 | expect(result[6]).to.equal(3); 43 | expect(result[7]).to.equal('laststring'); 44 | expect(result[8]).to.equal(true); 45 | }); 46 | 47 | }); -------------------------------------------------------------------------------- /tests/merge.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.merge()', function () { 6 | 7 | it('should merge two objects together into a new object', function () { 8 | var obj1 = { 9 | a: 1, 10 | b: null, 11 | c: undefined 12 | }; 13 | 14 | var obj2 = { 15 | d: function () {}, 16 | e: 'hello', 17 | f: {} 18 | }; 19 | 20 | var merged = fn.merge(obj1, obj2); 21 | 22 | expect(merged).to.not.equal(obj1); 23 | expect(merged).to.not.equal(obj2); 24 | expect(merged.a).to.equal(1); 25 | expect(merged.b).to.be.null; 26 | expect(merged.c).to.be.undefined; 27 | expect(merged.d).to.be.a('function'); 28 | expect(merged.e).to.equal('hello'); 29 | expect(merged.f).to.be.an('object'); 30 | }); 31 | 32 | it('should overwrite properties as objects are merged from right into left', function () { 33 | var obj1 = { 34 | a: 1, 35 | b: null, 36 | c: undefined 37 | }; 38 | 39 | var obj2 = { 40 | a: function () {}, 41 | e: 'hello', 42 | f: {} 43 | }; 44 | 45 | var obj3 = { 46 | b: 8, 47 | g: 'world', 48 | f: false 49 | }; 50 | 51 | var merged = fn.merge(obj1, obj2, obj3); 52 | 53 | expect(merged).to.not.equal(obj1); 54 | expect(merged).to.not.equal(obj2); 55 | expect(merged).to.not.equal(obj3); 56 | expect(merged.a).to.be.a('function'); 57 | expect(merged.b).to.equal(8); 58 | expect(merged.c).to.be.undefined; 59 | expect(merged.e).to.equal('hello'); 60 | expect(merged.g).to.equal('world'); 61 | }); 62 | 63 | }); -------------------------------------------------------------------------------- /tests/reduce.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.reduce()', function () { 6 | 7 | it('should fold an array of numbers into a single number', function () { 8 | var numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; 9 | 10 | var result = fn.reduce(function (accumulator, value) { 11 | return accumulator + value; 12 | }, 0, numbers); 13 | 14 | expect(result).to.equal(45); 15 | }); 16 | 17 | it('should fold an array of strings into a single string', function () { 18 | var strings = [ 'hello', 'world', 'foo', 'bar', 'baz' ]; 19 | 20 | var result = fn.reduce(function (accumulator, value) { 21 | return accumulator + value; 22 | }, '', strings); 23 | 24 | expect(result).to.equal('helloworldfoobarbaz'); 25 | }); 26 | 27 | it('should fold an array of arrays into a single array', function () { 28 | var arrays = [ [1, 2], [3, 4], [5, 6] ]; 29 | 30 | var result = fn.reduce(function (accumulator, value) { 31 | return fn.concat(accumulator, value); 32 | }, [], arrays); 33 | 34 | expect(result).to.have.length(6); 35 | expect(result[0]).to.equal(1); 36 | expect(result[1]).to.equal(2); 37 | expect(result[2]).to.equal(3); 38 | expect(result[3]).to.equal(4); 39 | expect(result[4]).to.equal(5); 40 | expect(result[5]).to.equal(6); 41 | }); 42 | 43 | it('should fold an array of objects into a single array', function () { 44 | var people = [ { name: 'Bill' }, { name: 'Jim' }, { name: 'Steve' } ]; 45 | 46 | var result = fn.reduce(function (accumulator, value) { 47 | accumulator.push(value.name); 48 | return accumulator; 49 | }, [], people); 50 | 51 | expect(result).to.have.length(3); 52 | expect(result[0]).to.equal('Bill'); 53 | expect(result[1]).to.equal('Jim'); 54 | expect(result[2]).to.equal('Steve'); 55 | }); 56 | 57 | }); -------------------------------------------------------------------------------- /tests/each.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.each()', function () { 6 | 7 | it('should iterate over all the elements in a collection', function () { 8 | var collection = [1, 'string', true]; 9 | var count = 0; 10 | 11 | fn.each(function () { 12 | count++; 13 | return false; 14 | }, collection); 15 | 16 | expect(count).to.equal(3); 17 | }); 18 | 19 | it('should be passed a value as the first argument', function () { 20 | var collection = [1, 'string', true]; 21 | var values = []; 22 | 23 | fn.each(function (value) { 24 | values.push(value); 25 | }, collection); 26 | 27 | expect(values).to.have.length(3); 28 | expect(values[0]).to.equal(1); 29 | expect(values[1]).to.equal('string'); 30 | expect(values[2]).to.equal(true); 31 | }); 32 | 33 | it('should be passed an index as the second argument', function () { 34 | var collection = [1, 'string', true]; 35 | var indices = []; 36 | 37 | fn.each(function (value, index) { 38 | indices.push(index); 39 | }, collection); 40 | 41 | expect(indices).to.have.length(3); 42 | expect(indices[0]).to.equal(0); 43 | expect(indices[1]).to.equal(1); 44 | expect(indices[2]).to.equal(2); 45 | }); 46 | 47 | it('should be passed the collection as the third argument', function () { 48 | var collection = [1, 'string', true]; 49 | 50 | fn.each(function (value, index, copy) { 51 | expect(copy).to.equal(collection); 52 | }, collection); 53 | }); 54 | 55 | it('should apply additional arguments to the handler', function () { 56 | var collection = [1, 2, 3]; 57 | 58 | fn.each(function (value, index, collection, four, five, six) { 59 | expect(four).to.equal(4); 60 | expect(five).to.equal(5); 61 | expect(six).to.equal(6); 62 | }, collection, [4, 5, 6]); 63 | }); 64 | 65 | }); -------------------------------------------------------------------------------- /tests/memoize.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.memoize()', function () { 6 | 7 | it('should cache the return value of a function without recomputing if the serializer remains unchanged', function (done) { 8 | var getTime = fn.memoize(function () { 9 | return Date.now(); 10 | }); 11 | 12 | var now = getTime('now'); 13 | 14 | setTimeout(function () { 15 | expect(now).to.equal(getTime('now')); 16 | done(); 17 | }, 0); 18 | }); 19 | 20 | it('should recompute the return value of a function if the serializer changes', function (done) { 21 | var getTime = fn.memoize(function () { 22 | return Date.now(); 23 | }); 24 | 25 | var then = getTime('then'); 26 | 27 | setTimeout(function () { 28 | expect(then).to.not.equal(getTime('now')); 29 | done(); 30 | }, 500); 31 | }); 32 | 33 | it('should apply the arguments to original function', function () { 34 | var echo = fn.memoize(function (a, b, c) { 35 | return [a, b, c]; 36 | }); 37 | 38 | var value = echo(1, 'a', true); 39 | 40 | expect(value).to.include.members([1, 'a', true]); 41 | }); 42 | 43 | it('should allow overriding of the cache key serializer', function () { 44 | var didSerialize = false; 45 | 46 | var echo = fn.memoize(function (a, b, c) { 47 | return [a, b, c]; 48 | }, function serialize(values) { 49 | didSerialize = true; 50 | return values[0].toString() + ' ' + values[1].toString() + values[2].toString(); 51 | }); 52 | 53 | var value = echo(1, 'a', true); 54 | 55 | expect(value).to.include.members([1, 'a', true]); 56 | expect(didSerialize).to.be.true; 57 | }); 58 | 59 | }); 60 | 61 | describe('.memoize.serialize()', function () { 62 | 63 | it('should serialize with type and JSON.stringify', function () { 64 | var obj = { 65 | a: 1, 66 | b: true, 67 | c: 'aliens' 68 | }; 69 | 70 | var key1 = fn.memoize.serialize([obj]); 71 | var key2 = fn.memoize.serialize([true]); 72 | var key3 = fn.memoize.serialize([3]); 73 | var key4 = fn.memoize.serialize(['aliens']); 74 | 75 | expect(key1).to.equal((fn.type(obj) + '|' + JSON.stringify(obj))); 76 | expect(key2).to.equal('boolean|true'); 77 | expect(key3).to.equal('number|3'); 78 | expect(key4).to.equal('string|\"aliens\"'); 79 | }); 80 | 81 | }); -------------------------------------------------------------------------------- /tests/op.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.op', function () { 6 | 7 | describe('+', function () { 8 | it('should add two numbers', function () { 9 | expect( fn.op['+'](1, 2) ).to.equal(3); 10 | }); 11 | 12 | it('should concatenate two strings', function () { 13 | expect( fn.op['+']('hello', 'world') ).to.equal('helloworld'); 14 | }); 15 | }); 16 | 17 | describe('-', function () { 18 | it('should subtract two numbers', function () { 19 | expect( fn.op['-'](3, 2) ).to.equal(1); 20 | }); 21 | }); 22 | 23 | describe('*', function () { 24 | it('should multiply two numbers', function () { 25 | expect( fn.op['*'](3, 2) ).to.equal(6); 26 | }); 27 | }); 28 | 29 | describe('/', function () { 30 | it('should divide two numbers', function () { 31 | expect( fn.op['/'](6, 2) ).to.equal(3); 32 | }); 33 | }); 34 | 35 | describe('==', function () { 36 | it('should weakly compare two values', function () { 37 | expect( fn.op['=='](3, 3) ).to.be.true; 38 | expect( fn.op['=='](false, 0) ).to.be.true; 39 | expect( fn.op['=='](false, 1) ).to.be.false; 40 | expect( fn.op['=='](null, undefined) ).to.be.true; 41 | expect( fn.op['=='](1/0, Infinity) ).to.be.true; 42 | expect( fn.op['==']('hello', 'hello') ).to.be.true; 43 | expect( fn.op['==']({}, {}) ).to.be.false; 44 | }); 45 | }); 46 | 47 | describe('===', function () { 48 | it('should strongly compare two values', function () { 49 | expect( fn.op['==='](3, 3) ).to.be.true; 50 | expect( fn.op['==='](false, 0) ).to.be.false; 51 | expect( fn.op['==='](false, 1) ).to.be.false; 52 | expect( fn.op['==='](null, undefined) ).to.be.false; 53 | expect( fn.op['==='](1/0, Infinity) ).to.be.true; 54 | expect( fn.op['===']('hello', 'hello') ).to.be.true; 55 | expect( fn.op['===']({}, {}) ).to.be.false; 56 | }); 57 | }); 58 | 59 | describe('++', function () { 60 | it('should increment a number', function () { 61 | expect( fn.op['++'](6) ).to.equal(7); 62 | expect( fn.op['++'](10) ).to.equal(11); 63 | expect( fn.op['++'](0) ).to.equal(1); 64 | }); 65 | }); 66 | 67 | describe('--', function () { 68 | it('should decrement a number', function () { 69 | expect( fn.op['--'](6) ).to.equal(5); 70 | expect( fn.op['--'](10) ).to.equal(9); 71 | expect( fn.op['--'](0) ).to.equal(-1); 72 | }); 73 | }); 74 | 75 | }); -------------------------------------------------------------------------------- /tests/is.js: -------------------------------------------------------------------------------- 1 | var fn = require('../build/fn'); 2 | var chai = require('chai'); 3 | var expect = chai.expect; 4 | 5 | describe('.is()', function () { 6 | 7 | it('should match a string to a string', function () { 8 | expect( fn.is('string', 'string') ).to.be.true; 9 | }); 10 | 11 | it('should not match a string to a number', function () { 12 | expect( fn.is('string', 'number') ).to.be.false; 13 | }); 14 | 15 | it('should match a number to a number', function () { 16 | expect( fn.is(123, 'number') ).to.be.true; 17 | }); 18 | 19 | it('should not match a number to a string', function () { 20 | expect( fn.is(123, 'string') ).to.be.false; 21 | }); 22 | 23 | it('should match true to a boolean', function () { 24 | expect( fn.is(true, 'boolean') ).to.be.true; 25 | }); 26 | 27 | it('should not match true to a string', function () { 28 | expect( fn.is(true, 'string') ).to.be.false; 29 | }); 30 | 31 | it('should match an array to array', function () { 32 | expect( fn.is([], 'array') ).to.be.true; 33 | }); 34 | 35 | it('should not match an array to object', function () { 36 | expect( fn.is([], 'object') ).to.be.false; 37 | }); 38 | 39 | it('should match an object to object', function () { 40 | expect( fn.is({}, 'object') ).to.be.true; 41 | }); 42 | 43 | it('should not match an object to array', function () { 44 | expect( fn.is({}, 'array') ).to.be.false; 45 | }); 46 | 47 | it('should match a Date to date', function () { 48 | expect( fn.is(new Date(), 'date') ).to.be.true; 49 | }); 50 | 51 | it('should not match a Date to number', function () { 52 | expect( fn.is(new Date(), 'number') ).to.be.false; 53 | }); 54 | 55 | it('should match undefined to undefined', function () { 56 | expect( fn.is(undefined, 'undefined') ).to.be.true; 57 | }); 58 | 59 | it('should not match undefined to null', function () { 60 | expect( fn.is(undefined, 'null') ).to.be.false; 61 | }); 62 | 63 | it('should match null to null', function () { 64 | expect( fn.is(null, 'null') ).to.be.true; 65 | }); 66 | 67 | it('should not match null to undefined', function () { 68 | expect( fn.is(null, 'undefined') ).to.be.false; 69 | }); 70 | 71 | it('should match function to function', function () { 72 | expect( fn.is(function () {}, 'function') ).to.be.true; 73 | }); 74 | 75 | it('should not match function to object', function () { 76 | expect( fn.is(function () {}, 'object') ).to.be.false; 77 | }); 78 | 79 | it('should match a Regex to regexp', function () { 80 | expect( fn.is(new RegExp(), 'regexp') ).to.be.true; 81 | }); 82 | 83 | it('should not match a Regex to object', function () { 84 | expect( fn.is(new RegExp(), 'object') ).to.be.false; 85 | }); 86 | 87 | }); --------------------------------------------------------------------------------