diff --git a/src/index.js b/src/index.js index e8a181ee..8160c8cd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,3 @@ - import initArray from './init-array' import reduce from './reduce-to-tally' import flatten from './flatten' @@ -28,6 +27,7 @@ import searchAndReplace from './search-and-replace' import sqrt from './sqrt' import toPower from './to-power' import mod from './mod' +import shallowEqual from './shallow-equal' import swapCase from './swap-case' export { @@ -60,5 +60,6 @@ export { sqrt, toPower, mod, + shallowEqual, swapCase, } diff --git a/src/shallow-equal.js b/src/shallow-equal.js new file mode 100644 index 00000000..4f653aca --- /dev/null +++ b/src/shallow-equal.js @@ -0,0 +1,43 @@ +export default shallowEqual + +function haveEqualKeys(a, b) { + const keysA = Object.keys(a) + const keysB = Object.keys(b) + return keysA.length === keysB.length +} + +function isNullOrNonObject(obj) { + return typeof obj !== 'object' || obj === null +} + +function compareKeys(objA, objB) { + const keysA = Object.keys(objA) + const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB) + for (let i = 0; i < keysA.length; i++) { + if (!bHasOwnProperty(keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) { + return false + } + } + + return true +} + +/** + * This method will shallow compare two objects + * + * @param {Object} objA - first object to compare + * @param {Object} objB - second object to compare + * @returns {boolean} - result of comparison - true if objects are shallow equal + */ + +function shallowEqual(objA, objB) { + if (objA === objB) { + return true + } + + if (isNullOrNonObject(objA) || isNullOrNonObject(objB) || !haveEqualKeys(objA, objB)) { + return false + } + + return compareKeys(objA, objB) +} diff --git a/test/shallow-equal.test.js b/test/shallow-equal.test.js new file mode 100644 index 00000000..845db54c --- /dev/null +++ b/test/shallow-equal.test.js @@ -0,0 +1,130 @@ +import test from 'ava' +import {shallowEqual} from '../src' + +test('Compares two equal objects', t => { + const a = { + a: 1, + b: 2, + c: 'test' + } + + const b = { + a: 1, + b: 2, + c: 'test' + } + + const actual = shallowEqual(a, b) + const expected = true + t.deepEqual(actual, expected) +}) + +test('Compares two equal objects symmetrically', t => { + const a = { + a: 1, + b: 2, + c: 'test' + } + + const b = { + a: 1, + b: 2, + c: 'test' + } + + t.deepEqual(shallowEqual(a, b), shallowEqual(b, a)) +}) + +test('Compares two inequal objects', t => { + const a = { + a: 1, + b: 2 + } + + const b = { + a: 1, + b: 2, + c: 'test' + } + + const actual = shallowEqual(a, b) + const expected = false + t.deepEqual(actual, expected) +}) + +test('Compares two inequal objects symmetrically', t => { + const b = { + a: 1, + b: 2 + } + + const a = { + a: 1, + b: 3 + } + + t.deepEqual(shallowEqual(a, b), shallowEqual(b, a)) +}) + +test('Compares only own properties of given objects', t => { + function A() { + this.a = 1 + this.b = 2 + this.c = 'test' + } + + A.prototype.anotherProp = 12345 + + const a = new A() + const b = { + a: 1, + b: 2, + c: 'test' + } + + const actual = shallowEqual(a, b) + const expected = true + t.deepEqual(actual, expected) +}) + +test('Compares only own properties of given objects symmetrically', t => { + function A() { + this.a = 1 + this.b = 2 + this.c = 'test' + } + + A.prototype.anotherProp = 12345 + + const a = new A() + const b = { + a: 1, + b: 2, + c: 'test' + } + + t.deepEqual(shallowEqual(a, b), shallowEqual(b, a)) +}) + +test('Returns true when the same object is compared to itself', t => { + const a = { + a: 1, + b: 'test' + } + + const actual = shallowEqual(a, a) + const expected = true + t.deepEqual(actual, expected) +}) + + +test('Returns false when one of the objects is null', t => { + const a = { + a: 1, + b: 'test' + } + + const actual = shallowEqual(a, null) + const expected = false + t.deepEqual(actual, expected) +}) \ No newline at end of file