Created
August 5, 2017 18:22
-
-
Save uniibu/49cfd3f8b27464792b1b88f444c0b0c1 to your computer and use it in GitHub Desktop.
native counterpart of some lodash functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const assert = require('assert'); | |
/** | |
* Determines if two values are equal(performs deep comparison). | |
* | |
* @param {*} obj The first value to compare from | |
* @param {*} other The value to compare to | |
* @return {boolean} True if equal, False otherwise. | |
*/ | |
const isEqual = (obj, other) => { | |
try { | |
if (typeof obj === 'function') { | |
assert.deepStrictEqual(obj, other); | |
} | |
assert.deepEqual(obj, other); | |
} catch (e) { | |
return false; | |
} | |
return true; | |
}; | |
/** | |
* Determines if array. | |
* | |
* @param {array} arg The argument | |
* @return {boolean} True if array, False otherwise. | |
*/ | |
const isArray = Array.isArray; | |
/** | |
* Determines if value is not null and has a type of object | |
* | |
* @param {object} value The value | |
* @return {boolean} True if objectlike, False otherwise. | |
*/ | |
const isObjectLike = (value) => { | |
return value !== null && typeof value === 'object'; | |
}; | |
/** | |
* Determines if value is a string | |
* | |
* @param {string} value The value | |
* @return {boolean} True if string, False otherwise. | |
*/ | |
const isString = value => { | |
return !(typeof value !== 'string') || !(value.constructor.name !== 'String'); | |
}; | |
/** | |
* Returns a function that performs isEqual between a given object and source | |
* | |
* @param {object} needle The object of property values to match. | |
* @return {function} Returns a new spec function | |
*/ | |
const matches = (needle) => { | |
return haystack => { | |
if (needle === haystack) { | |
return true; | |
} | |
return Object.keys(needle).every(key => isEqual(needle[key], haystack[key])); | |
}; | |
}; | |
/** | |
* Determines if object and source matches by invoking the customizer to compare values. | |
* | |
* @param {object} obj The object to inspect | |
* @param {object} src The object to match | |
* @param {(Function)} customizer The function to customize comparisons. | |
* @return {boolean} True if object is a match, False otherwise. | |
*/ | |
const isMatchWith = (obj, src, customizer) => { | |
customizer = typeof customizer === 'function' ? customizer : undefined; | |
if (!customizer) { | |
return isEqual(obj, src); | |
} | |
return Object.keys(obj).every(key => customizer(obj[key], src[key], key, obj, src)); | |
}; | |
/** | |
* Flattens an array single-level deep. We could have used Array.concat but it too slow compared | |
* to lodash's flatten. https://github.com/elidoran/flatten-array | |
* Note: This mutates the array, to prevent that, wrap it like flatten([array]) | |
* | |
* @param {array} array The array to flatten | |
* @return {array} The flattend array | |
*/ | |
const flatten = array => { | |
let value; | |
for (let i = 0; i < array.length;) { | |
value = array[i]; | |
if (Array.isArray(value)) { | |
if (value.length > 0) { | |
value.unshift(i, 1); | |
array.splice.apply(array, value); | |
value.splice(0, 2); | |
} else { | |
array.splice(i, 1); | |
} | |
} else { | |
i++; | |
} | |
} | |
return array; | |
}; | |
/** | |
* Removes falsy values from an array. We could have used Array.filter(Boolean) but again it's | |
* too slow compared to lodash's compact. https://jsperf.com/remove-falsy-values-from-array | |
* https://stackoverflow.com/a/16752942 | |
* Note: This mutates the array | |
* | |
* @param {array} array The array to inspect | |
* @return {array} The array with falsy values removed | |
*/ | |
const compact = array => { | |
let index = -1, | |
length = array == null ? 0 : array.length, | |
resIndex = 0, | |
result = []; | |
while (++index < length) { | |
let value = array[index]; | |
if (value) { | |
result[resIndex++] = value; | |
} | |
} | |
return result; | |
}; | |
/** | |
* Returns the all array values except the first,we could have used | |
* ([first, ...rest]) => rest; but its again the slowest | |
* https://jsperf.com/get-tail-of-array | |
* | |
* @param {array} The array to inspect | |
* @return {array} The array with first value removed | |
*/ | |
const tail = array => { | |
let index = -1, result = [], | |
length = array == null ? 0 : array.length + index; | |
if (length < 1) { | |
return []; | |
} | |
while (++index < length) { | |
result.push(array[index + 1]); | |
} | |
return result; | |
}; | |
/** | |
* Capitalized the First letter of a string, and lowercase the rest | |
* | |
* @param {string} string The string to inspect | |
* @return {string} The capitalized string | |
*/ | |
const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); | |
/** | |
* Returns an object with keys omitted | |
* | |
* @param {object} obj The object to inspect | |
* @param {array|string} keys The key/s to remove from the object | |
* @return {object} The Object with omitted keys | |
*/ | |
const omit = (obj, keys) => { | |
const target = {}; | |
for (const i in obj) { | |
if (!keys.includes(i)) { | |
target[i] = obj[i]; | |
} | |
} | |
return target; | |
}; | |
/** | |
* Returns a new array with only the first occurence of each element is kept | |
* We could have used Array.from(new Set(arr)) or even new Set(...arr) but | |
* its too slow compared to lodash's | |
* | |
* @param {array} arr The array to inspect | |
* @return {array} The new array with duplicate removed | |
*/ | |
const uniq = array => { | |
let index = -1, | |
length = array.length, | |
result = [], | |
seen = result; | |
outer: | |
while (++index < length) { | |
let value = array[index], | |
computed = value; | |
value = value !== 0 ? value : 0; | |
let seenIndex = seen.length; | |
while (seenIndex--) { | |
if (seen[seenIndex] === computed) { | |
continue outer; | |
} | |
} | |
result.push(value); | |
} | |
return result; | |
}; | |
module.exports = { | |
isEqual, | |
isArray, | |
isObjectLike, | |
isString, | |
matches, | |
isMatchWith, | |
flatten, | |
compact, | |
tail, | |
capitalize, | |
omit, | |
uniq | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment