204 lines
5.4 KiB
Markdown
204 lines
5.4 KiB
Markdown
# samsam
|
|
|
|
> Same same, but different
|
|
|
|
`samsam` is a collection of predicate and comparison functions useful for
|
|
identifiying the type of values and to compare values with varying degrees of
|
|
strictness.
|
|
|
|
`samsam` is a general-purpose library with no dependencies. It works in browsers
|
|
(including old and rowdy ones, like IE6) and Node. It will define itself as an
|
|
AMD module if you want it to (i.e. if there's a `define` function available).
|
|
|
|
## Predicate functions
|
|
|
|
|
|
### `isArguments(value)`
|
|
|
|
Returns `true` if `value` is an `arguments` object, `false` otherwise.
|
|
|
|
|
|
### `isNegZero(value)`
|
|
|
|
Returns `true` if `value` is `-0`.
|
|
|
|
|
|
### `isElement(value)`
|
|
|
|
Returns `true` if `value` is a DOM element node. Unlike
|
|
Underscore.js/lodash, this function will return `false` if `value` is an
|
|
*element-like* object, i.e. a regular object with a `nodeType` property that
|
|
holds the value `1`.
|
|
|
|
### `isSet(value)`
|
|
|
|
Returns `true` if `value` is a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).
|
|
|
|
|
|
## Comparison functions
|
|
|
|
|
|
### `identical(x, y)`
|
|
|
|
Strict equality check according to EcmaScript Harmony's `egal`.
|
|
|
|
**From the Harmony wiki:**
|
|
|
|
> An egal function simply makes available the internal `SameValue` function
|
|
from section 9.12 of the ES5 spec. If two values are egal, then they are not
|
|
observably distinguishable.
|
|
|
|
`identical` returns `true` when `===` is `true`, except for `-0` and
|
|
`+0`, where it returns `false`. Additionally, it returns `true` when
|
|
`NaN` is compared to itself.
|
|
|
|
|
|
### `deepEqual(actual, expectation)`
|
|
|
|
Deep equal comparison. Two values are "deep equal" if:
|
|
|
|
* They are identical
|
|
* They are both date objects representing the same time
|
|
* They are both arrays containing elements that are all deepEqual
|
|
* They are objects with the same set of properties, and each property
|
|
in `actual` is deepEqual to the corresponding property in `expectation`
|
|
|
|
* `actual` can have [symbolic properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) that are missing from `expectation`
|
|
|
|
|
|
### `match(object, matcher)`
|
|
|
|
Partial equality check. Compares `object` with matcher according a wide set of
|
|
rules:
|
|
|
|
#### String matcher
|
|
|
|
In its simplest form, `match` performs a case insensitive substring match.
|
|
When the matcher is a string, `object` is converted to a string, and the
|
|
function returns `true` if the matcher is a case-insensitive substring of
|
|
`object` as a string.
|
|
|
|
```javascript
|
|
samsam.match("Give me something", "Give"); //true
|
|
samsam.match("Give me something", "sumptn"); // false
|
|
samsam.match({ toString: function () { return "yeah"; } }, "Yeah!"); // true
|
|
```
|
|
|
|
The last example is not symmetric. When the matcher is a string, the `object`
|
|
is coerced to a string - in this case using `toString`. Changing the order of
|
|
the arguments would cause the matcher to be an object, in which case different
|
|
rules apply (see below).
|
|
|
|
|
|
#### Boolean matcher
|
|
|
|
Performs a strict (i.e. `===`) match with the object. So, only `true`
|
|
matches `true`, and only `false` matches `false`.
|
|
|
|
|
|
#### Regular expression matcher
|
|
|
|
When the matcher is a regular expression, the function will pass if
|
|
`object.test(matcher)` is `true`. `match` is written in a generic way, so
|
|
any object with a `test` method will be used as a matcher this way.
|
|
|
|
```javascript
|
|
samsam.match("Give me something", /^[a-z\s]$/i); // true
|
|
samsam.match("Give me something", /[0-9]/); // false
|
|
samsam.match({ toString: function () { return "yeah!"; } }, /yeah/); // true
|
|
samsam.match(234, /[a-z]/); // false
|
|
```
|
|
|
|
|
|
#### Number matcher
|
|
|
|
When the matcher is a number, the assertion will pass if `object == matcher`.
|
|
|
|
```javascript
|
|
samsam.match("123", 123); // true
|
|
samsam.match("Give me something", 425); // false
|
|
samsam.match({ toString: function () { return "42"; } }, 42); // true
|
|
samsam.match(234, 1234); // false
|
|
```
|
|
|
|
|
|
#### Function matcher
|
|
|
|
When the matcher is a function, it is called with `object` as its only
|
|
argument. `match` returns `true` if the function returns `true`. A strict
|
|
match is performed against the return value, so a boolean `true` is required,
|
|
truthy is not enough.
|
|
|
|
```javascript
|
|
// true
|
|
samsam.match("123", function (exp) {
|
|
return exp == "123";
|
|
});
|
|
|
|
// false
|
|
samsam.match("Give me something", function () {
|
|
return "ok";
|
|
});
|
|
|
|
// true
|
|
samsam.match({
|
|
toString: function () {
|
|
return "42";
|
|
}
|
|
}, function () { return true; });
|
|
|
|
// false
|
|
samsam.match(234, function () {});
|
|
```
|
|
|
|
|
|
#### Object matcher
|
|
|
|
As mentioned above, if an object matcher defines a `test` method, `match`
|
|
will return `true` if `matcher.test(object)` returns truthy.
|
|
|
|
If the matcher does not have a test method, a recursive match is performed. If
|
|
all properties of `matcher` matches corresponding properties in `object`,
|
|
`match` returns `true`. Note that the object matcher does not care if the
|
|
number of properties in the two objects are the same - only if all properties in
|
|
the matcher recursively matches ones in `object`.
|
|
|
|
```javascript
|
|
// true
|
|
samsam.match("123", {
|
|
test: function (arg) {
|
|
return arg == 123;
|
|
}
|
|
});
|
|
|
|
// false
|
|
samsam.match({}, { prop: 42 });
|
|
|
|
// true
|
|
samsam.match({
|
|
name: "Chris",
|
|
profession: "Programmer"
|
|
}, {
|
|
name: "Chris"
|
|
});
|
|
|
|
// false
|
|
samsam.match(234, { name: "Chris" });
|
|
```
|
|
|
|
|
|
#### DOM elements
|
|
|
|
`match` can be very helpful when comparing DOM elements, because it allows
|
|
you to compare several properties with one call:
|
|
|
|
```javascript
|
|
var el = document.getElementById("myEl");
|
|
|
|
samsam.match(el, {
|
|
tagName: "h2",
|
|
className: "item",
|
|
innerHTML: "Howdy"
|
|
});
|
|
```
|