Skip to content

Instantly share code, notes, and snippets.

@aercolino
Created June 7, 2014 12:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aercolino/e72bd4f4754a74deb969 to your computer and use it in GitHub Desktop.
Save aercolino/e72bd4f4754a74deb969 to your computer and use it in GitHub Desktop.
A jQuery plugin for equality comparisons of JavaScript scalars and objects.
$.equals = function( a, b, options ) {
options = $.extend({
// if true, in case of inequality, a trace of the first difference is logged to the console
verbose: false,
// use 'strict' for ===, 'abstract' for ==
comparison: 'strict',
// if true, an item is compared, otherwise it is ignored
// receives a value and a key, returns true or false
filter: function () {
return true;
}
}, options || {});
var outmost = false;
if (typeof options.trace == 'undefined') {
outmost = true;
options.trace = [];
}
if (options.comparison == 'strict' ? a === b : a == b) {
return true;
}
var ta = $.type(a);
var tb = $.type(b);
if (! (ta == tb)) {
log(['types', ta, tb, a, b]);
return false;
}
var aa = decompose(a, options.filter);
var bb = decompose(b, options.filter);
var la = aa.keys.length;
var lb = bb.keys.length;
if (! (la == lb)) {
log(['lengths', la, lb, a, b]);
return false;
}
var length = la; // == lb
if (length == 0) { // a and b are scalar
return a === b;
}
// compare corresponding elements
for (var i = 0; i < length; i++) {
var key = aa.keys[i];
var a_value = a[key];
var b_value = b[key];
var equal = $.equals( a_value, b_value, options );
if (! equal) {
log(['values at key "' + key + '"', a_value, b_value, a, b]);
return false;
}
}
if (outmost) {
log(['values', null, null, a, b]);
}
return true;
//---
// returns true if the given object is a scalar (not in JavaScript terms, though...)
function isScalar(object) {
return object === null || /undefined|boolean|number|string/.test(typeof object);
}
// returns a plain object with the given object's items correspondingly split into keys and values arrays
function decompose(object, filter) {
if (isScalar(object)) {
return {
keys: [],
values: filter(object) ? object : null
};
}
var keys = [];
var values = [];
for (var key in object) {
var value = object[key];
if (filter(value, key)) {
keys.push(key);
values.push(value);
}
}
return {keys: keys, values: values};
}
// returns a plain object with the given decomposed's keys and values arrays correspondingly joined into items
// note that
// (1) compose(decompose(plain_object)) == plain_object
// (2) compose(decompose(non_plain_object)) != non_plain_object
function compose(decomposed) {
var result = {};
for (var i = 0, iTop = decomposed.keys.length; i < iTop; i++) {
result[decomposed.keys[i]] = decomposed.values[i];
}
return result;
}
// logs given data to the console if it's the outmost log, otherwise it only remembers
function log(data) {
if (! options.verbose) return;
options.trace.push(data);
if (outmost) {
console_log('');
while (options.trace.length) {
console_log(' ');
}
}
//---
function console_log(prefix) {
var top = options.trace.pop();
var data = compose({keys: ['difference', 'a_value', 'b_value', 'a', 'b'], values: top});
if ('values' == data.difference) {
console.log(' ($.equals)', prefix + 'comparing(', data.a, ', ', data.b, ')\n',
'($.equals)', prefix + ' found different values');
}
else {
console.log(' ($.equals)', prefix + 'comparing(', data.a, ', ', data.b, ')\n',
'($.equals)', prefix + ' found different', data.difference, data.a_value, '!=', data.b_value);
}
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment