pwnn / is.js
- суббота, 11 июня 2016 г. в 03:12:58
JavaScript
Minimalistic predicate library.
Minimalistic predicate library.
Node:
$ npm install --save @pwn/isBrowser:
<script src="path/to/is.min.js"></script>A code sample is worth a thousand words:
const is = require( '@pwn/is' )
is.array( [] ) // true
is.not.integer( 0 ) // false
is.propertyDefined( { foo : { bar : 0 } } , 'foo.bar' ) // true
is.equal( [ 1 , [ 2 , 3 ] ] , [ 1 , [ 2 , 3 ] ] ) // false
is.deepEqual( [ 1 , [ 2 , 3 ] ] , [ 1 , [ 2 , 3 ] ] ) // true
// use a third-party bundle
is.use( require( 'path/to/some/math/bundle' ) )
is.prime( 7 ) // trueAll checks, or predicates in is.js terminology, takes two general forms:
is.predicate( ...args ) - Checks whether certain condition met.is.not.predicate( ...args ) - The inverse of its corresponding positive check.That's it! What's next?
is.js.TL;DR
A bundle is simply a way of organizing related predicates.
bundle:nil
bundle:number
bundle:string
bundle:boolean
bundle:object
bundle:array
bundle:type
bundle:equality
Checks whether given value is null.
is.null( null ) // true
is.null( undefined ) // falseChecks whether given value is undefined.
is.undefined( null ) // false
is.undefined( undefined ) // trueChecks whether given value exists, i.e, not null nor undefined.
is.exist( null ) // false
is.exist( undefined ) // falseChecks whether given value is either null or undefined.
is.nil( null ) // true
is.nil( undefined ) // trueChecks whether given value is a number.
is.number( 0 ) // true
is.number( Number.NaN ) // true
is.number( Number.POSITIVE_INFINITY ) // true
is.number( Number.NEGATIVE_INFINITY ) // true
is.number( '0' ) // false
is.number( new Number( 0 ) ) // falseChecks whether given value is a numeral, i.e:
is.numeral( null ) // false
is.numeral( undefined ) // false
is.numeral( true ) // false
is.numeral( false ) // false
is.numeral( Symbol( 0 ) ) // false
is.numeral( Symbol.for( 0 ) ) // false
is.numeral( { valueOf() { return 0 } } ) // false
is.numeral( [ 0 ] ) // false
is.numeral( () => 0 ) // false
is.numeral( '' ) // false
is.numeral( 'one' ) // false
is.numeral( '1px' ) // false
is.numeral( ' 0xFF ' ) // true
is.numeral( '1e1' ) // true
is.numeral( '1.1E-1' ) // true
is.numeral( '-1' ) // true
is.numeral( '1.1' ) // true
is.numeral( new Number( 1 ) ) // true
is.numeral( new String( '-1.1' ) ) // true
is.numeral( Number.NaN ) // false
is.numeral( Number.POSITIVE_INFINITY ) // false
is.numeral( Number.NEGATIVE_INFINITY ) // falseChecks whether given value is NaN.
is.nan( 0 ) // false
is.nan( Number.NaN ) // true
is.nan( new Number( Number.NaN ) ) // false
is.nan( Number.POSITIVE_INFINITY ) // false
is.nan( Number.NEGATIVE_INFINITY ) // false
is.nan( 'one' ) // falseChecks whether given value is an odd number.
is.odd( 1 ) // true
is.odd( 2 ) // false
is.odd( '1' ) // false
is.odd( '2' ) // false
is.odd( new Number( 1 ) ) // false
is.odd( new Number( 2 ) ) // false
is.odd( Number.NaN ) // false
is.odd( Number.POSITIVE_INFINITY ) // false
is.odd( Number.NEGATIVE_INFINITY ) // falseChecks whether given value is an even number.
is.even( 1 ) // false
is.even( 2 ) // true
is.even( '1' ) // false
is.even( '2' ) // false
is.even( new Number( 1 ) ) // false
is.even( new Number( 2 ) ) // false
is.even( Number.NaN ) // false
is.even( Number.POSITIVE_INFINITY ) // false
is.even( Number.NEGATIVE_INFINITY ) // falseChecks whether given value is a finite number.
is.finite( 0 ) // true
is.finite( '0' ) // false
is.finite( Number.NaN ) // false
is.finite( Number.POSITIVE_INFINITY ) // false
is.finite( Number.NEGATIVE_INFINITY ) // falseChecks whether given value is an infinite number, i.e,
Number.POSITIVE_INFINITY or Number.NEGATIVE_INFINITY.
is.infinite( 0 ) // false
is.infinite( '0' ) // false
is.infinite( Number.NaN ) // false
is.infinite( Number.POSITIVE_INFINITY ) // true
is.infinite( Number.NEGATIVE_INFINITY ) // trueChecks whether given value is an integer.
is.integer( 0 ) // true
is.integer( '0' ) // false
is.integer( new Number( 0 ) ) // false
is.integer( 0.1 ) // false
is.integer( Number.NaN ) // false
is.integer( Number.POSITIVE_INFINITY ) // false
is.integer( Number.NEGATIVE_INFINITY ) // false
is.integer( Number.MAX_SAFE_INTEGER ) // true
is.integer( Number.MIN_SAFE_INTEGER ) // true
is.integer( Number.MAX_SAFE_INTEGER + 1 ) // true
is.integer( Number.MIN_SAFE_INTEGER - 1 ) // trueChecks whether given value is a safe integer.
is.safeInteger( 0 ) // true
is.safeInteger( '0' ) // false
is.safeInteger( new Number( 0 ) ) // false
is.safeInteger( 0.1 ) // false
is.safeInteger( Number.NaN ) // false
is.safeInteger( Number.POSITIVE_INFINITY ) // false
is.safeInteger( Number.NEGATIVE_INFINITY ) // false
is.safeInteger( Number.MAX_SAFE_INTEGER ) // true
is.safeInteger( Number.MIN_SAFE_INTEGER ) // true
is.safeInteger( Number.MAX_SAFE_INTEGER + 1 ) // false
is.safeInteger( Number.MIN_SAFE_INTEGER - 1 ) // falseChecks whether given value is a string.
is.string( 'lipsum' ) // true
is.string( new String( 'lipsum' ) ) // falseChecks whether given value is an empty string, i.e, a string with whitespace characters only.
is.emptyString( '' ) // true
is.emptyString( ' ' ) // true
is.emptyString( '\f\n\r\t' ) // true
is.emptyString( '\u0009\u000A\u000B\u000C\u000D\u0020' ) // true
is.emptyString( 'lipsum' ) // falseChecks whether one string may be found within another string.
is.substring( 'ps' , 'lipsum' ) // true
is.substring( 'sp' , 'lipsum' ) // false
is.substring( [ 'ps' ] , 'lipsum' ) // true; `substring` will be converted to a string as needed
is.substring( 'ps' , [ 'lipsum' ] ) // false; `string` must be a string
is.substring( 'ps' , 'lipsum' , 2 ) // true
is.substring( 'ps' , 'lipsum' , 3 ) // false
is.substring( 'ps' , 'lipsum' , 3.14 ) // true; non-integer offset will be omitted and defaults to 0
is.substring( 'ps' , 'lipsum' , -4 ) // true; supports negative offset
is.substring( 'ps' , 'lipsum' , 6 ) // false; offset out of range
is.substring( 'ps' , 'lipsum' , -7 ) // false; offset out of rangeChecks whether string starts with prefix.
is.prefix( 'lip' , 'lipsum' ) // true
is.prefix( 'sum' , 'lipsum' ) // false
is.prefix( 'lip' , [ 'lipsum' ] ) // false; `string` must be a string
is.prefix( [ 'lip' ] , 'lipsum' ) // true - `prefix` will be converted to a string as neededChecks whether string ends with suffix.
is.suffix( 'sum' , 'lipsum' ) // true
is.suffix( 'lip' , 'lipsum' ) // false
is.suffix( 'sum' , [ 'lipsum' ] ) // false; `string` must be a string
is.suffix( [ 'sum' ] , 'lipsum' ) // true - `suffix` will be converted to a string as neededChecks whether given value is a boolean.
is.boolean( 1 ) // false
is.boolean( 0 ) // false
is.boolean( true ) // true
is.boolean( false ) // true
is.boolean( new Boolean( true ) ) // false
is.boolean( new Boolean( false ) ) // falseChecks whether given value is an object.
is.object( null ) // false
is.object( undefined ) // false
is.object( 0 ) // false
is.object( new Number( 0 ) ) // true
is.object( '' ) // false
is.object( new String( '' ) ) // true
is.object( true ) // false
is.object( new Boolean( true ) ) // true
is.object( Symbol() ) // false
is.object( Symbol.for( 'is' ) ) // false
is.object( {} ) // true
is.object( [] ) // true
is.object( function () {} ) // trueChecks whether given value is an empty object, i.e, an object without any own, enumerable, string keyed properties.
is.emptyObject( {} ) // true
is.emptyObject( { foo : 'bar' } ) // false
is.emptyObject( Object.create( { foo : 'bar' } ) ) // true; ignore inherited properties
is.emptyObject( Object.defineProperty( {} , 'foo' , { value : 'bar' } ) ) // true; ignore non-enumerable properties
is.emptyObject( { [ Symbol() ] : 0 } ) // true; ignore non-string-keyed properties
Checks whether path is a direct or inherited property of object.
is.propertyDefined( Object.create( { foo : 'bar' } ) , 'foo' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.bar' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.bar.baz' ) // true
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.qux.baz' ) // false
is.propertyDefined( { foo : { bar : { baz : 0 } } } , 'foo.bar.baz.qux' ) // falseChecks whether object conforms to schema.
A schema is an object whose properties are functions that takes
these parameters(in order):
These functions, or validators, are called for each corresponding key
in object to check whether object conforms to the schema. An object is
said to be conforms to the schema if all validators passed.
In strict mode(where strict=true), is.conforms also checks whether
object and schema has the same set of own, enumerable, string-keyed
properties, in addition to check whether all validators passed.
is.conforms(
{ name : '@pwn/is' , access : 'public' } ,
{ name : is.exist }
) // true
is.conforms(
{ name : '@pwn/is' , access : 'public' } ,
{ description : is.string }
) // false; key `description` does not exist on `object`
is.conforms(
{ name : '@pwn/is' , access : 'public' } ,
{
name( value , key , context ) {
return is.exist( value ) && context.access === 'public'
}
}
) // true
//
// strict mode
//
is.conforms(
{
name : '@pwn/is' ,
access : 'public'
} ,
{
name( value , key , context ) {
return is.string( value ) && value.length >= 3
}
} ,
true // enable strict mode
) // false; `object` has extraneous propertiesChecks whether given value is an array.
is.array( [] ) // true
is.array( '' ) // false
is.array( document.scripts ) // false
is.array( function() {} ) // falseChecks whether given value is an array-like object.
An object is qualified as array-like if it has a property named
length that is a positive safe integer. As a special case, functions
are never qualified as array-like.
is.arrayLikeObject( [] ) // true
is.arrayLikeObject( '' ) // false
is.arrayLikeObject( document.scripts ) // true
is.arrayLikeObject( function() {} ) // falseChecks whether given array or array-like object contains certain element.
value.is.inArray( 2 , [ 1 , 2 , 3 ] ) // true
is.inArray( 4 , [ 1 , 2 , 3 ] ) // false
is.inArray( 2 , [ 1 , 2 , 3 ] , 1 ) // true
is.inArray( 2 , [ 1 , 2 , 3 ] , 2 ) // false
is.inArray( 2 , [ 1 , 2 , 3 ] , -2 ) // true; supports negative offset
is.inArray( 2 , [ 1 , 2 , 3 ] , 3 ) // false; offset out of range
is.inArray( 2 , [ 1 , 2 , 3 ] , -4 ) // false; offset out of range
is.inArray( [ 2 ] , [ 1 , [ 2 ] , 3 ] ) // false; default comparator is `is.equal`
is.inArray( [ 2 ] , [ 1 , [ 2 ] , 3 ] , 0 , is.deepEqual ) // true
is.inArray( [ 2 ] , [ 1 , [ 2 ] , 3 ] , is.deepEqual ) // true; `offset` can be omitted when passing a custom comparator only
is.inArray( 2 , [ 1 , 2 , 3 ] , ( val , arrMember ) => val === arrMember ) // true; `comparator` takes two parameters, the element to search and the array element of current iterationChecks whether given values are of the same type.
is.sameType( 0 , 0 ) // true
is.sameType( 0 , '0' ) // false
is.sameType( 0 , new Number( 0 ) ) // false
is.sameType( 0 , Number.NaN ) // true
is.sameType( [] , {} ) // falseChecks whether given value is a primitive.
is.primitive( null ) // true
is.primitive( undefined ) // true
is.primitive( 0 ) // true
is.primitive( new Number( 0 ) ) // false
is.primitive( '' ) // true
is.primitive( new String( '' ) ) // false
is.primitive( true ) // true
is.primitive( new Boolean( true ) ) // false
is.primitive( Symbol() ) // true
is.primitive( Symbol.for( 'is' ) ) // true
is.primitive( {} ) // false
is.primitive( [] ) // false
is.primitive( function() {} ) // falseChecks whether given value is a Date object.
is.date( new Date() ) // trueChecks whether given value is an Error object.
is.error( new Error() ) // true
is.error( new TypeError() ) // trueChecks whether given value is a function.
is.function( function () {} ) // true
is.function( () => null ) // true
is.function( new Function() ) // trueChecks whether given value is a Map object.
is.map( new Map() ) // trueChecks whether given value is a RegExp object.
is.regexp( /^/ ) // true
is.regexp( new RegExp() ) // trueChecks whether given value is a Set object.
is.set( new Set() ) // trueChecks whether given value is a symbol.
is.symbol( Symbol() ) // true
is.symbol( Symbol.for( 'is' ) ) // trueChecks whether given values are equal, using SameValueZero algorithm.
is.equal( null , undefined ) // false
is.equal( 0 , 0 ) // true
is.equal( 0 , '0' ) // false
is.equal( +0 , -0 ) // true; SameValueZero
is.equal( Number.NaN , Number.NaN ) // true; SameValueZero
is.equal( [] , [] ) // falseChecks whether given values are deeply equal, i.e:
Type( value ) !== Type( other ), returns false.is.deepEqual( null , undefined ) // false
is.deepEqual( 0 , 0 ) // true
is.deepEqual( 0 , '0' ) // false
is.deepEqual( +0 , -0 ) // true; SameValueZero
is.deepEqual( Number.NaN , Number.NaN ) // true; SameValueZero
is.deepEqual( [ 1 , { foo : [ 2 , [ 3 , 4 ] ] , bar : { baz : 5 } } ] , [ 1 , { foo : [ 2 , [ 3 , 4 ] ] , bar : { baz : 5 } } ] ) // true
is.deepEqual( Object.create( { foo : 1 } ) , Object.create( { foo : 2 } ) ) // true; only own, enumerable, string-keyed properties are checkedPredicates are essentially functions that checks whether certain condition met based on passed in arguments. They are packaged in various bundles. Conceptually, a bundle is simply a way of organizing related predicates. Implementation-wise, a bundle is a just a function that takes two parameters:
util:object - The utility object.is:object - The is export.The util object defines a method called addPredicate that allows you to define new predicates:
util.addPredicate( name:string , predicate:function )
- name - The name of the predicate.
- predicate - The predicate function.
Once defined, the predicate will be available on both is and is.not — util.addPredicate wraps the predicate in a delegate function and automatically handles positive/negative cases for you.
Still confused? Take a look at this sample bundle:
// my_bundle.js
// `util` and `is` are passed in as free variables, so you don't
// need to call `require( '@pwn/is' )`
module.exports = function bundle( util , is ) {
util.addPredicate( 'positive' , function isPositive( value ) {
return is.number( value ) && value > 0
} )
util.addPredicate( 'negative' , function isNegative( value ) {
return is.number( value ) && value < 0
} )
}To use a bundle, simple call is.use:
is.use( bundle:function )
const is = require( '@pwn/is' )
// import all predicates from my_bundle.js
is.use( require( 'path/to/my_bundle' ) )
is.positive( +1 ) // true
is.not.positive( -1 ) // true
is.negative( -1 ) // true
is.not.negative( +1 ) // true