index.md 5.44 KB
Newer Older
YazhouChen's avatar
YazhouChen committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
# 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"
});
```