Each time I get a handle on Javascript concepts, low and behold, something new is presented which, luckily, builds on previous challenges. This challenge introduced associative arrays, which is an an abstract data type made of a collection of key:value pairs. Keys are sometimes referred to as name, or in other languages, a hash.
You may have heard that everything in Javascript is an object, which true... kinda. Javascripts design is one of a simple object-based paradigm. Objects can be compared to real-life things such as shoes: They have properties such as size, color, a specific designer. Javascript in the same also have properties that define who they are and what they do.
Values such as Booleans, Numbers and Strings are primitive values - in other words, not objects. But what you will find is sometimes they are. That is the beauty of a loosely typed language like Javascript. But on the flip side, because the language is so forgiving, it can get you, dear programmer, in trouble.
Below, we are to create a function that takes in two arguments and iterates through an array of objects (first argument) and returns an array with matching properties and values pairs of the second argument. The property and value of the source object must be present in the collection object in order to be included in the returned array.
Given these variables:
var collection = [ { first: "Romeo", last: "Montague" },
{ first: "Mercutio", last: null },
{ first: "Tybalt", last: "Capulet" } ];
var source = [{last: "Capulet"}];
The third object from the collection argument [{last: "Capulet"}] should be returned as a new Array as it has the that property-value pair as the second argument.
One of the many methods of the Object constructor is Object.hasOwnProperty() returns a boolean (true, false) depending on whether the object has the specified property.
obj.hasOwnProperty(prop)
Another is Object.keys(), which returns an new array composed of the Object's enumerable properties in the same order as a for...in loop would, without checking down the prototype chain.
Object.keys(obj)
How this differs from the in operator is this method does not do a check through the objects prototype chain. Using these two methods, along with filter() and every() I was able to successfully compose the function:
function where(collection, source) {
var sourceKeys = Object.keys(source);
return collection.filter(function (obj) {
return sourceKeys.every(function (key) {
return obj.hasOwnProperty(key) && obj[key] === source[key];
});
});
}
where([{ first: "Romeo", last: "Montague" }, { first: "Mercutio",last: null }, { first: "Tybalt", last: "Capulet"}], { last: "Capulet" });
console.log(sourceKeys);` //outputs ["last"]
Basically, the function will filter through the collection obj return an new array of values the callback finds is true. Every() method executes the callback function in the new array until it finds a false value. Finally, obj.hasOwnProperty() returns objects whose keys match those equal to source[key].
I hope this succinctly explains what is going on with the above function. The most challenging part for me with using higher order functions is syntax; knowing when and where to chain functions together to get the appropriate solution.