Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Converting Objects

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement Lodash methods to convert objects.

toArray

The Lodash toArray method transforms a given value to an array.

For instance, we can implement as follows:

const toArray = val => {
  if (val instanceof String || typeof val === 'string') {
    return val.split('');
  } else if (val instanceof Object) {
    return Object.values(val)
  }
  return [];
}

In the code above, we checked if val is a string by using the instanceof operator for strings created with the String constructor and use the typeof operator to check for primitive strings.

Then we split the strings into with the split method in this case.

If val is an object, then we return the values with Object.values .

Otherwise, we return an empty array.

Then we can call it as follows:

console.log(toArray({
  'a': 1,
  'b': 2
}));

console.log(toArray('abc'));

console.log(toArray(1));

console.log(toArray(null));

The first call should return [1, 2] , the 2nd returns ['a', 'b', 'c'] , and the last 2 return an empty array.

toFinite

Lodash’s toFinite method converts values to finite values.

We can do that by checking for Infinity and -Infinity and then returning the finite values accordingly.

For instance, we can write the following function to do that:

const toFinite = (val) => {
  if (val === Infinity) {
    return Number.MAX_VALUE
  } else if (val === -Infinity) {
    return -Number.MAX_VALUE
  }
  return isNaN(val) ? 0 : +val;
}

In the code above, we checked if val is Infinity or -Infinity and return Number.MAX_VALUE and — Number.MAX_VALUE respectively.

Otherwise, we use the isNaN function to check is val can be converted to a number. The isNaN function tries to convert the argument into a number before checking if the converted value is NaN or not.

If it’s not NaN , then we return val converted to a number. Otherwise, we return 0.

Then we can call it as follows:

console.log(toFinite(3.2));
console.log(toFinite(Number.MIN_VALUE));
console.log(toFinite(Infinity));
console.log(toFinite('3.2'));

Then we get:

3.2
5e-324
1.7976931348623157e+308
3.2

from the console log output.

toInteger

Lodash’s toInteger method converted the given value to an integer.

We can implement our own toInteger function as follows:

const toInteger = (val) => {
  if (val === Infinity) {
    return Number.MAX_VALUE
  } else if (val === -Infinity) {
    return -Number.MAX_VALUE
  }
  return isNaN(val) ? 0 : Math.round(+val);
}

In the code above, we check if val is Infinity our -Infinity , then we return Number.MAX_VALUE and -Number.MAX_VALUE respectively.

Otherwise, we check if val can be converted to a number, and then call Math.round if the number can be converted to a number.

Then we can call it as follows:

console.log(toInteger(3.2));
console.log(toInteger(Number.MIN_VALUE));
console.log(toInteger(Infinity));
console.log(toInteger('3.2'));

We then get the following values logged for each function call:

3
0
1.7976931348623157e+308
3

toLength

The toLength method converts a number to an integer that’s suitable to be used as the length of an array-like object.

We can implement our own toLength method as follows:

const toLength = (val) => {
  if (val === Infinity || Math.round(+val) > 4294967295) {
    return 4294967295
  } else if (+val < 0) {
    return 0
  }
  return isNaN(val) ? 0 : Math.round(+val);
}

In the code above, we check that if val is Infinity or if the converted integer is bigger than 4294967295, which is the maximum length of an array.

If it is, then we return 4294967295. If val converted to a number if negative, then we return 0.

Otherwise, we call Math.round to round the converted number if the converted value is a number.

Then when we call it as follows:

console.log(toLength(3.2));
console.log(toLength(Number.MIN_VALUE));
console.log(toLength(Infinity));
console.log(toLength('3.2'));

We get the following values from the console log outputs:

3
0
4294967295
3

Conclusion

We can implement Lodash’s object conversion methods easily ourselves.

The toArray method can be implemented by splitting strings or getting the values of an object.

The toFinite method can be implemented by returning the biggest integer in JavaSscript if it’s Infinity and the negative of that if it’s -Infinity . Otherwise, if it’s a number, then we return the 0 if the value isn’t a number or the number itself if it can be converted into a number.

Likewise, the toLength method can implemented in a similar way except that instead of returning the largest integer for Infinity and negative of that for -Infinity , we return the maximum length of a JavaScript array for Infinity and 0 for -Infinity or any other negative number.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Comparison and Constructors

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we look at how to clone objects in a variety of ways and do comparisons on object values.

conformsTo

The Lodash conformsTo checks if all object entries conform to a given predicate.

We can check the value of each property to see if the condition is met as follows:

const conformsTo = (obj, predicate) => {
  for (const [key, val] of Object.entries(obj)) {
    if (typeof predicate[key] === 'function' && predicate[key](val)) {
      return true
    }
  }
  return false;
}

In the code above, we used the Object.entries method to get all the entries of an object. Then we used destructuring to destructure the array entries returned by Object.entries to the keys and values.

Then we check val against the predicate[key] function, which returns the true if the condition in it is met and false otherwise.

Then we can use it as follows:

const result = conformsTo({
  a: 1
}, {
  a: x => x >= 0
});

Then since a has value 1, it conformsTo should return true because each value if bigger than or equal to 0 as the predicate has condition x >= 0 as the value of the a property.

eq

The Lodash eq object compares 2 objects to see if they’re equivalent using the SameValueZero algorithm.

We can implement our own eq function by doing the comparing for +0 and -0 ourselves and using Object.is for everything else:

const eq = (a, b) => {
  if (a === +0 && b === -0 ||
    a === -0 && b === +0 ||
    a === 0 && b === -0 ||
    a === 0 && b === +0 ||
    a === +0 && b === 0 ||
    a === -0 && b === 0) {
    return true;
  }
  return Object.is(a, b);
}

In the code above, we compared the 0 values with different signs and return true for all of them.

Then we use object Object.is for all other comparisons. When we call it as follows:

const result = eq(1, -0);

We get that result is false and if we call it as follows:

const result = eq(+0, -0);

we get that result is true .

gt

The Lodash gt method returns a boolean indicating if one number is bigger than the other.

We can just use the > operator to do the comparison ourselves. We can implement it as follows:

const gt = (a, b) => a > b;

Then we can call it as follows:

const result = gt(2, 1);

result is true .

gte

Like gt , we can implement the Lodash gte method with the >= operator.

We can write the following function as follows:

const gt = (a, b) => a >= b;

Then when we write the following code:

const result = gt(2, 2);

We get that result is true .

isArray

The Lodash isArray method checks is a value is an array. We can just use the Array.isArray method to check if an object is an array.

Therefore, we can write the following code to implement our own isArray method:

const isArray = arr => Array.isArray(arr);

In the code above, we just called Array.isArray to check if arr is an array.

Then we can call it as follows:

const result = isArray([1, 2, 3]);

We get that result is true .

isDate

The Lodash isDate method checks if an object is an instance of the Date constructor.

We can use the constructor.name property of an object to check what constructor the object is created from.

Therefore, we can write the following to implement our own isDate function:

const isDate = date => date.constructor.name == 'Date'

Then we can call the function as follows:

const result = isDate(1);

and get that result is false . If we call it as follows:

const result = isDate(new Date());

We get that result is true .

Conclusion

We can use the constuctor.name property to get the name of the constructor that an object is created from.

To check if an object is an array, we can use the Array.isArray method to implement it.

To compare values for equality, we can use === and Object.is . Finally, we can use the > and >= to check if something is bigger than another.

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Picking Items and Getting Sizes

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement Lodash methods that let us pick items and getting sizes of collections.

reject

The reject method takes a collection of items and a predicate with the items that we don’t want to include in the returned array and return an array with the items that are opposite of the predicate.

We can implement this as follows:

const reject = (collection, predicate) => collection.filter(c => !predicate(c));

In the code above, we just called filter with a callback that returns the predicate call negated.

Then we can call it as follows:

const users = [{
    'user': 'foo',
    'active': false
  },
  {
    'user': 'bar',
    'active': true
  }
];

const result = reject(users, o => !o.active);

The code above rejects the users entries that have active set to false as the value.

This means that we return the entries with active set to true . Therefore, we get:

[
  {
    "user": "bar",
    "active": true
  }
]

as the value of result .

sample

The Lodash sample method returns a random element from a collection. Since plain JavaScript has a Math.random method, we can use that to get a random element from an array as follows:

const sample = (collection) => {
  const index = Math.random() * (collection.length);
  return collection[Math.floor(index)];
};

In the code above, we just used the Math.random method which is multiplied by the collection.length to get the index . Then we take the floor of it to get the actual index.

Then when we call it as follows:

const result = sample([1, 2, 3]);

We get a random item from the array.

sampleSize

The sampleSize method takes an array to get the items from and the size of the sample, we want to get.

It returns the array that takes random elements from the collection up to the given size .

We can implement the sampleSize method as follows:

const sampleSize = (collection, size) => {
  let sampled = [];
  for (let i = 1; i <= size; i++) {
    const index = Math.random() * (collection.length);
    sampled.push(collection.splice(index, 1)[0]);
  }
  return sampled;
};

In the code above, we created a loop that gets the index of the collection to pick by calling the Math.random multiplied by collection.length .

Then we called splice on collection to remove that element from collection and push it into the sampled array.

Once we have enough sampled items, we return sampled .

Then when we call it as follows:

const result = sampleSize([1, 2, 3], 2);

We get 2 different items from the array we passed in as the value of result .

shuffle

The Lodash shuffle method returns an array that’s a shuffled version of the original array.

We can implement it as follows:

const shuffled = (collection) => {
  let shuffled = [];
  const originalLength = collection.length;
  for (let i = originalLength - 1; i >= 0; i--) {
    const index = Math.random() * (collection.length);
    shuffled.push(collection.splice(index, 1)[0]);
  }
  return shuffled;
};

In the code above, we created a loop that loop through the collection ‘s original length. Then we get a random item from the collection and put it into the shuffled array as we did with the sampleSize function above.

Once the loop is done, we returned the shuffled array.

Then when we call shuffle as follows:

const result = shuffled([1, 2, 3]);

We get a shuffled version of the array we passed in.

size

The size method gets the size of a collection, which can be an array or an object. Since we have the length property of arrays and we have the Object.keys method for objects, we can implement it with the following code:

const size = (collection) => {
  if (Array.isArray(collection)) {
    return collection.length;
  } else {
    return Object.keys(collection).length;
  }
};

In the code above, we check if collection is an array. If it is, then we return the length property of it.

Otherwise, we return the array returned by Object.keys ‘s length property.

When we call it as follows:

const result = size([1, 2, 3]);

We get that result is 3.

When we call it with an object:

const result = size({
  'a': 1,
  'b': 2
});

We get that result is 2.

Conclusion

The reject method can be implemented with the filter method by negating the predicate in the callback.

The sample family of methods and shuffle can be implemented with Math.random and splice .

Finally, the size method can be implemented with the length of the array or length of the array returned by Object.keys .

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Transforming Objects

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement some object methods with plain JavaScript.

toPlainObject

The Lodash’s toPlainObject method converts an object to a plain object by merging in the inherited enumerable properties into the object itself.

We can implement it by using the Object.create method

Then we use the Object.getPrototypeOf method and then merge them into the object’s own properties.

For instance, we can implement it as follows:

const toPlainPObject = (obj) => {
  let plainObj = Object.create(null);
  plainObj = {
    ...obj
  };
  let prototype = Object.getPrototypeOf(obj)
  while (prototype) {
    plainObj = {
      ...plainObj,
      ...prototype
    }
    prototype = Object.getPrototypeOf(prototype)
  }
  return plainObj;
}

In the code above, we have our toPlainObject function, which takes the obj parameter containing the object that we want to convert to a plain object.

We then create a new object with Object.create with the argument null , which creates a plain object by creating an object without a prototype.

Then we use the spread operator to merge obj ‘s own properties into plainObj .

Next, we call Object.getPrototypeOf with obj passed in to get obj ‘s prototype. Then we use a while loop to merge the prototype’s properties into plainObj and go up the prototype chain with:

prototype = Object.getPrototypeOf(prototype)

In the end, we return plainObj .

Now when we call it as follows:

function Foo() {
  this.a = 1;
}

Foo.prototype.b = 2;
console.log(toPlainPObject(new Foo()));

We get the console log output is {a: 1, b: 2} .

toSafeInteger

Lodash’s toSafeInteger method converts a value to a safe integer. It does this by checking for Infinity and -Infinity and then return the maximum safe integer and the maximum safe integer multiplied by 1 respectively.

We can implement it as follows:

const toSafeInteger = val => {
  if (val === Infinity) {
    return Number.MAX_SAFE_INTEGER
  } else if (val === -Infinity) {
    return -1 * Number.MAX_SAFE_INTEGER
  }
  return isNaN(+val) ? 0 : Math.round(+val);
}

In the code above, we check if val is Infinity or -Infinity . If it’s Infinity , then we return Number.MAX_SAFE_INTEGER . If val is -Infinity , then we return -Number.MAX_SAFE_INTEGER .

Otherwise, we check if val can be converted to a number by calling isNaN . If it returns true then we return 0, otherwise, we call Math.round with +val after it’s converted to a number.

Then we can call it as follows:

console.log(toSafeInteger(3.2));
console.log(toSafeInteger(Number.MIN_VALUE));
console.log(toSafeInteger(Infinity));
console.log(toSafeInteger('3.2'));

Then we get the following output from each of the respectively:

3
0
9007199254740991
3

toString

Lodash’s toString method coverts a given value to a string. An empty string is returned for null and undefined values.

For instance, we can implement it as follows:

const toString = val => {
  if (Object.is(val, -0)) {
    return '-0'
  } else if (Object.is(val, +0)) {
    return '+0'
  } else if (Object.is(val, null) || Object.is(val, undefined)) {
    return ''
  } else if (Array.isArray(val)) {
    return val.join(',');
  }
  return JSON.stringify(val);
}

In the code above, we used Object.is to check whether val is one of the listed values. We use Object.is instead of === because -0 and +0 are considered different with Object.is .

If val isn’t -0 , +0 , null or undefined then we use JSON.stringify to convert the object to a string.

Then we can call it as follows:

console.log(toString(null));
console.log(toString(-0));
console.log(toString([1, 2, 3]));

Then we get an empty string from the first console log, '-0' from the 2nd console log and 1,2,3 from the last console log.

invert

The Lodash invert method flips the keys and values of an object. If 2 properties have the same value, then the later one overwrites the earlier one.

We can do that ourselves with the Object.keys method to get the keys to populate a new object with the keys and values inverted as follows:

const invert = (obj) => {
  let invertedObj = {};
  for (const key of Object.keys(obj)) {
    invertedObj[obj[key]] = key;
  }
  return invertedObj;
}

In the code above, we created the invertedObj object. Then we loop through the keys by getting them with the Object.keys method and then looping through them with the for...of loop.

Then we populate the values of obj as the keys of invertedobj and the keys of obj as the values of invertedObj .

In the end, when we call it as follows:

const object = {
  'a': 1,
  'b': 2,
  'c': 1
};

console.log(invert(object));

We get {1: “c”, 2: “b”} logged from the console log output.

Conclusion

To implement the toPlainObject method, we can use the Object.getPrototype method to traverse the prototype chain of an object.

The toString and toSafeInteger methods are similar in that they both do a series of checks on the argument passed in and then return some values accordingly.

Finally, we can use Object.keys to get the keys of an object to implement invert .

Categories
Lodash

Learning JavaScript by Implementing Lodash Methods — Loops and Searching

Lodash is a very useful utility library that lets us work with objects and arrays easily.

However, now that the JavaScript standard library is catching up to libraries such as Lodash, we can implement many of the functions in simple ways.

In this article, we’ll look at how to implement some Lodash methods that deal with iterating through and searching for data.

forEachRight

The forEachRight method lets us loop through a collection from end to start. It only loops through arrays.

We can implement it using a regular for loop as follows:

const forEachRight = (collection, iteratee) => {
  for (let i = collection.length - 1; i >= 0; i--) {
    const result = iteratee(collection[i])
    if (result === false) {
      break;
    }
  }
}

In the code above, we have a for loop that loops through our collection in reverse.

Inside the loop, we call iteratee on each item that’s being looped through.

Then if the returned value of the iteratee returns false , we break the loop.

We can then call it as follows:

forEachRight([1, 2], (value) => {
  if (value === 1) {
    return false;
  }
  console.log(value);
});

Once the value is 1, the loop ends, so we get 2 logged only.

every

The Lodash every method checks that a predicate returns truthy for all elements in a collection.

Since plain JavaScript has an every method that does the same thing but called on the array instance instead of passing in an array, we can implement the Lodash as follows:

const every = (arr, predicate) => arr.every(predicate)

Then when we call it as follows:

const result = every([1, 2, 3], x => x > 0);

We get that result is true since every element is bigger than 0.

filter

Lodash’s filter method iterates all elements of a collection and returns an array of all elements that return truthy.

JavaScript array has a filter method that does the same thing, so we can use it as follows:

const filter = (arr, predicate) => arr.filter(predicate)

The JavaScript filter method is part of the array instance, so we just call it to do the filtering for us.

Then when we call it as follows:

const result = filter([1, 2, 3], x => x > 1);

We get that result is [2, 3] since they’re bigger than 1.

find

find loops over a collection and returns the first item that meets the given condition.

The Lodash version of find also takes a starting index to search for.

We can implement our own Lodash find method with the plain JavaScript find method as follows:

const find = (arr, predicate, start) => arr.slice(start).find(predicate)

In the code above, we called slice with the start index to start searching from the start index with find .

Then we can call it as follows:

const result = find([4, 1, 2, 3], x => x > 1, 1);

And we get that result is 2 because it’s the first element that’s bigger than 1 and it’s index 1 or after.

findLast

The Lodash findLast method finds an element from right to left. The arguments are the same as find .

We can implement it with a for loop as follows:

const findLast = (arr, predicate, start = arr.length - 1) => {
  for (let i = start; i >= 0; i--) {
    if (predicate(arr[i])) {
      return arr[i]
    }
  }
}

In the code above, we looped through arr in reverse and call predicate on each entry until one returns a truthy value. If that’s the case, then that item is returned.

Then when we call it as follows:

const result = findLast([4, 1, 2, 3], x => x > 1, 1);

We get that result is 4 since that’s the first element in position less than or equal to 1 that’s bigger than 1.

Conclusion

The Lodash forEachRight method can be implemented with a for loop to loop through the items in reverse.

The every method can be implemented with plain JavaScript’s every method.

Likewise, the filter and find methods can be implemented with the plain JS version.

Finally, the findLast method can be implemented with a for loop that loop through items in reverse.