## Object

#### bindAll

Binds methods of an object to the object itself, overwriting the existing method.

Use `Array.forEach()` to return a `function` that uses `Function.apply()` to apply the given context (`obj`) to `fn` for each function specified.

    const bindAll = (obj, ...fns) =>
      fns.forEach(
        fn => (
          (f = obj[fn]),
          (obj[fn] = function() {
            return f.apply(obj);
          })
        )
      );

examples

    var view = {
      label: 'docs',
      click: function() {
        console.log('clicked ' + this.label);
      }
    };
    bindAll(view, 'click');
    jQuery(element).on('click', view.click); // Logs 'clicked docs' when clicked.

#### deepClone

Creates a deep clone of an object.

Use recursion. Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original. Use `Object.keys()` and `Array.forEach()` to determine which key-value pairs need to be deep cloned.

    const deepClone = obj => {
      let clone = Object.assign({}, obj);
      Object.keys(clone).forEach(
        key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
      );
      return Array.isArray(obj) ? (clone.length = obj.length) && Array.from(clone) : clone;
    };

examples

    const a = { foo: 'bar', obj: { a: 1, b: 2 } };
    const b = deepClone(a); // a !== b, a.obj !== b.obj

#### deepFreeze

Deep freezes an object.

Calls `Object.freeze(obj)` recursively on all unfrozen properties of passed object that are `instanceof` object.

    const deepFreeze = obj =>
      Object.keys(obj).forEach(
        prop =>
          !obj[prop] instanceof Object || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop])
      ) || Object.freeze(obj);

examples

    'use strict';

    const o = deepFreeze([1, [2, 3]]);

    o[0] = 3; // not allowed
    o[1][0] = 4; // not allowed as well

#### defaults

Assigns default values for all properties in an object that are `undefined`.

Use `Object.assign()` to create a new empty object and copy the original one to maintain key order, use `Array.reverse()` and the spread operator `...` to combine the default values from left to right, finally use `obj` again to overwrite properties that originally had a value.

    const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);

examples

    defaults({ a: 1 }, { b: 2 }, { b: 6 }, { a: 3 }); // { a: 1, b: 2 }

#### dig

Returns the target value in a nested JSON object, based on the given key.

Use the `in` operator to check if `target` exists in `obj`. If found, return the value of `obj[target]`, otherwise use `Object.values(obj)` and `Array.reduce()` to recursively call `dig` on each nested object until the first matching key/value pair is found.

    const dig = (obj, target) =>
      target in obj
        ? obj[target]
        : Object.values(obj).reduce((acc, val) => {
            if (acc !== undefined) return acc;
            if (typeof val === 'object') return dig(val, target);
          }, undefined);

examples

    const data = {
      level1: {
        level2: {
          level3: 'some data'
        }
      }
    };
    dig(data, 'level3'); // 'some data'
    dig(data, 'level4'); // undefined

#### equals

Performs a deep comparison between two values to determine if they are equivalent.

Check if the two values are identical, if they are both `Date` objects with the same time, using `Date.getTime()` or if they are both non-object values with an equivalent value (strict comparison). Check if only one value is `null` or `undefined` or if their prototypes differ. If none of the above conditions are met, use `Object.keys()` to check if both values have the same number of keys, then use `Array.every()` to check if every key in the first value exists in the second one and if they are equivalent by calling this method recursively.

    const equals = (a, b) => {
      if (a === b) return true;
      if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
      if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
      if (a === null || a === undefined || b === null || b === undefined) return false;
      if (a.prototype !== b.prototype) return false;
      let keys = Object.keys(a);
      if (keys.length !== Object.keys(b).length) return false;
      return keys.every(k => equals(a[k], b[k]));
    };

examples

    equals({ a: [2, { e: 3 }], b: [4], c: 'foo' }, { a: [2, { e: 3 }], b: [4], c: 'foo' }); // true

#### findKey

Returns the first key that satisfies the provided testing function. Otherwise `undefined` is returned.

Use `Object.keys(obj)` to get all the properties of the object, `Array.find()` to test the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object.

    const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));

examples

    findKey(
      {
        barney: { age: 36, active: true },
        fred: { age: 40, active: false },
        pebbles: { age: 1, active: true }
      },
      o => o['active']
    ); // 'barney'

#### findLastKey

Returns the last key that satisfies the provided testing function. Otherwise `undefined` is returned.

Use `Object.keys(obj)` to get all the properties of the object, `Array.reverse()` to reverse their order and `Array.find()` to test the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object.

    const findLastKey = (obj, fn) =>
      Object.keys(obj)
        .reverse()
        .find(key => fn(obj[key], key, obj));

examples

    findLastKey(
      {
        barney: { age: 36, active: true },
        fred: { age: 40, active: false },
        pebbles: { age: 1, active: true }
      },
      o => o['active']
    ); // 'pebbles'

#### flattenObject

Flatten an object with the paths for keys.

Use recursion. Use `Object.keys(obj)` combined with `Array.reduce()` to convert every leaf node to a flattened path node. If the value of a key is an object, the function calls itself with the appropriate `prefix` to create the path using `Object.assign()`. Otherwise, it adds the appropriate prefixed key-value pair to the accumulator object. You should always omit the second argument, `prefix`, unless you want every key to have a prefix.

    const flattenObject = (obj, prefix = '') =>
      Object.keys(obj).reduce((acc, k) => {
        const pre = prefix.length ? prefix + '.' : '';
        if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
        else acc[pre + k] = obj[k];
        return acc;
      }, {});

examples

    flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c': 1, d: 1 }

#### forOwn

Iterates over all own properties of an object, running a callback for each one.

Use `Object.keys(obj)` to get all the properties of the object, `Array.forEach()` to run the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object.

    const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));

examples

    forOwn({ foo: 'bar', a: 1 }, v => console.log(v)); // 'bar', 1

#### forOwnRight

Iterates over all own properties of an object in reverse, running a callback for each one.

Use `Object.keys(obj)` to get all the properties of the object, `Array.reverse()` to reverse their order and `Array.forEach()` to run the provided function for each key-value pair. The callback receives three arguments - the value, the key and the object.

    const forOwnRight = (obj, fn) =>
      Object.keys(obj)
        .reverse()
        .forEach(key => fn(obj[key], key, obj));

examples

    forOwnRight({ foo: 'bar', a: 1 }, v => console.log(v)); // 1, 'bar'

#### functions

Returns an array of function property names from own (and optionally inherited) enumerable properties of an object.

Use `Object.keys(obj)` to iterate over the object's own properties. If `inherited` is `true`, use `Object.get.PrototypeOf(obj)` to also get the object's inherited properties. Use `Array.filter()` to keep only those properties that are functions. Omit the second argument, `inherited`, to not include inherited properties by default.

    const functions = (obj, inherited = false) =>
      (inherited
        ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))]
        : Object.keys(obj)
      ).filter(key => typeof obj[key] === 'function');

examples

    function Foo() {
      this.a = () => 1;
      this.b = () => 2;
    }
    Foo.prototype.c = () => 3;
    functions(new Foo()); // ['a', 'b']
    functions(new Foo(), true); // ['a', 'b', 'c']

#### get

Retrieve a set of properties indicated by the given selectors from an object.

Use `Array.map()` for each selector, `String.replace()` to replace square brackets with dots, `String.split('.')` to split each selector, `Array.filter()` to remove empty values and `Array.reduce()` to get the value indicated by it.

    const get = (from, ...selectors) =>
      [...selectors].map(s =>
        s
          .replace(/\[([^\[\]]*)\]/g, '.$1.')
          .split('.')
          .filter(t => t !== '')
          .reduce((prev, cur) => prev && prev[cur], from)
      );

examples

    const obj = { selector: { to: { val: 'val to select' } }, target: [1, 2, { a: 'test' }] };
    get(obj, 'selector.to.val', 'target[0]', 'target[2].a'); // ['val to select', 1, 'test']

#### invertKeyValues

Inverts the key-value pairs of an object, without mutating it. The corresponding inverted value of each inverted key is an array of keys responsible for generating the inverted value. If a function is supplied, it is applied to each inverted key.

Use `Object.keys()` and `Array.reduce()` to invert the key-value pairs of an object and apply the function provided (if any). Omit the second argument, `fn`, to get the inverted keys without applying a function to them.

    const invertKeyValues = (obj, fn) =>
      Object.keys(obj).reduce((acc, key) => {
        const val = fn ? fn(obj[key]) : obj[key];
        acc[val] = acc[val] || [];
        acc[val].push(key);
        return acc;
      }, {});

examples

    invertKeyValues({ a: 1, b: 2, c: 1 }); // { 1: [ 'a', 'c' ], 2: [ 'b' ] }
    invertKeyValues({ a: 1, b: 2, c: 1 }, value => 'group' + value); // { group1: [ 'a', 'c' ], group2: [ 'b' ] }

#### lowercaseKeys

Creates a new object from the specified object, where all the keys are in lowercase.

Use `Object.keys()` and `Array.reduce()` to create a new object from the specified object. Convert each key in the original object to lowercase, using `String.toLowerCase()`.

    const lowercaseKeys = obj =>
      Object.keys(obj).reduce((acc, key) => {
        acc[key.toLowerCase()] = obj[key];
        return acc;
      }, {});

examples

    const myObj = { Name: 'Adam', sUrnAME: 'Smith' };
    const myObjLower = lowercaseKeys(myObj); // {name: 'Adam', surname: 'Smith'};

#### mapKeys

Creates an object with keys generated by running the provided function for each key and the same values as the provided object.

Use `Object.keys(obj)` to iterate over the object's keys. Use `Array.reduce()` to create a new object with the same values and mapped keys using `fn`.

    const mapKeys = (obj, fn) =>
      Object.keys(obj).reduce((acc, k) => {
        acc[fn(obj[k], k, obj)] = obj[k];
        return acc;
      }, {});

examples

    mapKeys({ a: 1, b: 2 }, (val, key) => key + val); // { a1: 1, b2: 2 }

#### mapValues

Creates an object with the same keys as the provided object and values generated by running the provided function for each value.

Use `Object.keys(obj)` to iterate over the object's keys. Use `Array.reduce()` to create a new object with the same keys and mapped values using `fn`.

    const mapValues = (obj, fn) =>
      Object.keys(obj).reduce((acc, k) => {
        acc[k] = fn(obj[k], k, obj);
        return acc;
      }, {});

examples

    const users = {
      fred: { user: 'fred', age: 40 },
      pebbles: { user: 'pebbles', age: 1 }
    };
    mapValues(users, u => u.age); // { fred: 40, pebbles: 1 }

#### matches

Compares two objects to determine if the first one contains equivalent property values to the second one.

Use `Object.keys(source)` to get all the keys of the second object, then `Array.every()`, `Object.hasOwnProperty()` and strict comparison to determine if all keys exist in the first object and have the same values.

    const matches = (obj, source) =>
      Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);

examples

    matches({ age: 25, hair: 'long', beard: true }, { hair: 'long', beard: true }); // true
    matches({ hair: 'long', beard: true }, { age: 25, hair: 'long', beard: true }); // false

#### matchesWith

Compares two objects to determine if the first one contains equivalent property values to the second one, based on a provided function.

Use `Object.keys(source)` to get all the keys of the second object, then `Array.every()`, `Object.hasOwnProperty()` and the provided function to determine if all keys exist in the first object and have equivalent values. If no function is provided, the values will be compared using the equality operator.

    const matchesWith = (obj, source, fn) =>
      Object.keys(source).every(
        key =>
          obj.hasOwnProperty(key) && fn
            ? fn(obj[key], source[key], key, obj, source)
            : obj[key] == source[key]
      );

examples

    const isGreeting = val => /^h(?:i|ello)$/.test(val);
    matchesWith(
      { greeting: 'hello' },
      { greeting: 'hi' },
      (oV, sV) => isGreeting(oV) && isGreeting(sV)
    ); // true

#### merge

Creates a new object from the combination of two or more objects.

Use `Array.reduce()` combined with `Object.keys(obj)` to iterate over all objects and keys. Use `hasOwnProperty()` and `Array.concat()` to append values for keys existing in multiple objects.

    const merge = (...objs) =>
      [...objs].reduce(
        (acc, obj) =>
          Object.keys(obj).reduce((a, k) => {
            acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k];
            return acc;
          }, {}),
        {}
      );

examples

    const object = {
      a: [{ x: 2 }, { y: 4 }],
      b: 1
    };
    const other = {
      a: { z: 3 },
      b: [2, 3],
      c: 'foo'
    };
    merge(object, other); // { a: [ { x: 2 }, { y: 4 }, { z: 3 } ], b: [ 1, 2, 3 ], c: 'foo' }

#### nest

Given a flat array of objects linked to one another, it will nest them recursively. Useful for nesting comments, such as the ones on reddit.com.

Use recursion. Use `Array.filter()` to filter the items where the `id` matches the `link`, then `Array.map()` to map each one to a new object that has a `children` property which recursively nests the items based on which ones are children of the current item. Omit the second argument, `id`, to default to `null` which indicates the object is not linked to another one (i.e. it is a top level object). Omit the third argument, `link`, to use `'parent_id'` as the default property which links the object to another one by its `id`.

    const nest = (items, id = null, link = 'parent_id') =>
      items
        .filter(item => item[link] === id)
        .map(item => ({ ...item, children: nest(items, item.id) }));

examples

    // One top level comment
    const comments = [
      { id: 1, parent_id: null },
      { id: 2, parent_id: 1 },
      { id: 3, parent_id: 1 },
      { id: 4, parent_id: 2 },
      { id: 5, parent_id: 4 }
    ];
    const nestedComments = nest(comments); // [{ id: 1, parent_id: null, children: [...] }]

#### objectFromPairs

Creates an object from the given key-value pairs.

Use `Array.reduce()` to create and combine key-value pairs.

    const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});

examples

    objectFromPairs([['a', 1], ['b', 2]]); // {a: 1, b: 2}

#### objectToPairs

Creates an array of key-value pair arrays from an object.

Use `Object.keys()` and `Array.map()` to iterate over the object's keys and produce an array with key-value pairs.

    const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);

examples

    objectToPairs({ a: 1, b: 2 }); // [ ['a', 1], ['b', 2] ]

#### omit

Omits the key-value pairs corresponding to the given keys from an object.

Use `Object.keys(obj)`, `Array.filter()` and `Array.includes()` to remove the provided keys. Use `Array.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs.

    const omit = (obj, arr) =>
      Object.keys(obj)
        .filter(k => !arr.includes(k))
        .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});

examples

    omit({ a: 1, b: '2', c: 3 }, ['b']); // { 'a': 1, 'c': 3 }

#### omitBy

Creates an object composed of the properties the given function returns falsey for. The function is invoked with two arguments: (value, key).

Use `Object.keys(obj)` and `Array.filter()`to remove the keys for which `fn` returns a truthy value. Use `Array.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs.

    const omitBy = (obj, fn) =>
      Object.keys(obj)
        .filter(k => !fn(obj[k], k))
        .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});

examples

    omitBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { b: '2' }

#### orderBy

Returns a sorted array of objects ordered by properties and orders.

Uses `Array.sort()`, `Array.reduce()` on the `props` array with a default value of `0`, use array destructuring to swap the properties position depending on the order passed. If no `orders` array is passed it sort by `'asc'` by default.

    const orderBy = (arr, props, orders) =>
      [...arr].sort((a, b) =>
        props.reduce((acc, prop, i) => {
          if (acc === 0) {
            const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
            acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
          }
          return acc;
        }, 0)
      );

examples

    const users = [{ name: 'fred', age: 48 }, { name: 'barney', age: 36 }, { name: 'fred', age: 40 }];
    orderBy(users, ['name', 'age'], ['asc', 'desc']); // [{name: 'barney', age: 36}, {name: 'fred', age: 48}, {name: 'fred', age: 40}]
    orderBy(users, ['name', 'age']); // [{name: 'barney', age: 36}, {name: 'fred', age: 40}, {name: 'fred', age: 48}]

#### pick

Picks the key-value pairs corresponding to the given keys from an object.

Use `Array.reduce()` to convert the filtered/picked keys back to an object with the corresponding key-value pairs if the key exists in the object.

    const pick = (obj, arr) =>
      arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});

examples

    pick({ a: 1, b: '2', c: 3 }, ['a', 'c']); // { 'a': 1, 'c': 3 }

#### pickBy

Creates an object composed of the properties the given function returns truthy for. The function is invoked with two arguments: (value, key).

Use `Object.keys(obj)` and `Array.filter()`to remove the keys for which `fn` returns a falsey value. Use `Array.reduce()` to convert the filtered keys back to an object with the corresponding key-value pairs.

    const pickBy = (obj, fn) =>
      Object.keys(obj)
        .filter(k => fn(obj[k], k))
        .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});

examples

    pickBy({ a: 1, b: '2', c: 3 }, x => typeof x === 'number'); // { 'a': 1, 'c': 3 }

#### renameKeys

Replaces the names of multiple object keys with the values provided.

Use `Object.keys()` in combination with `Array.reduce()` and the spread operator (`...`) to get the object's keys and rename them according to `keysMap`.

    const renameKeys = (keysMap, obj) =>
      Object.keys(obj).reduce(
        (acc, key) => ({
          ...acc,
          ...{ [keysMap[key] || key]: obj[key] }
        }),
        {}
      );

examples

    const obj = { name: 'Bobo', job: 'Front-End Master', shoeSize: 100 };
    renameKeys({ name: 'firstName', job: 'passion' }, obj); // { firstName: 'Bobo', passion: 'Front-End Master', shoeSize: 100 }

#### shallowClone

Creates a shallow clone of an object.

Use `Object.assign()` and an empty object (`{}`) to create a shallow clone of the original.

    const shallowClone = obj => Object.assign({}, obj);

examples

    const a = { x: true, y: 1 };
    const b = shallowClone(a); // a !== b

#### size

Get size of arrays, objects or strings.

Get type of `val` (`array`, `object` or `string`). Use `length` property for arrays. Use `length` or `size` value if available or number of keys for objects. Use `size` of a `Blob` object created from `val` for strings.

Split strings into array of characters with `split('')` and return its length.

    const size = val =>
      Array.isArray(val)
        ? val.length
        : val && typeof val === 'object'
          ? val.size || val.length || Object.keys(val).length
          : typeof val === 'string'
            ? new Blob([val]).size
            : 0;

examples

    size([1, 2, 3, 4, 5]); // 5
    size('size'); // 4
    size({ one: 1, two: 2, three: 3 }); // 3

#### transform

Applies a function against an accumulator and each key in the object (from left to right).

Use `Object.keys(obj)` to iterate over each key in the object, `Array.reduce()` to call the apply the specified function against the given accumulator.

    const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);

examples

    transform(
      { a: 1, b: 2, c: 1 },
      (r, v, k) => {
        (r[v] || (r[v] = [])).push(k);
        return r;
      },
      {}
    ); // { '1': ['a', 'c'], '2': ['b'] }

#### truthCheckCollection

Checks if the predicate (second argument) is truthy on all elements of a collection (first argument).

Use `Array.every()` to check if each passed object has the specified property and if it returns a truthy value.

    const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);

examples

    truthCheckCollection([{ user: 'Tinky-Winky', sex: 'male' }, { user: 'Dipsy', sex: 'male' }], 'sex'); // true

#### unflattenObject

Unflatten an object with the paths for keys.

Use `Object.keys(obj)` combined with `Array.reduce()` to convert flattened path node to a leaf node. If the value of a key contains a dot delimiter (`.`), use `Array.split('.')`, string transformations and `JSON.parse()` to create an object, then `Object.assign()` to create the leaf node. Otherwise, add the appropriate key-value pair to the accumulator object.

    const unflattenObject = obj =>
      Object.keys(obj).reduce((acc, k) => {
        if (k.indexOf('.') !== -1) {
          const keys = k.split('.');
          Object.assign(
            acc,
            JSON.parse(
              '{' +
                keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') +
                obj[k] +
                '}'.repeat(keys.length)
            )
          );
        } else acc[k] = obj[k];
        return acc;
      }, {});

examples

    unflattenObject({ 'a.b.c': 1, d: 1 }); // { a: { b: { c: 1 } }, d: 1 }