Programming languages are tools to express programmer intentions. Why, then, do we suffer the indignities of inelegant notation when we might, instead, bend the language to capture our meaning better?
If you’ve written code, you’ve likely accessed the first and last elements of an array:
var grades = [80, 90, 85]; grades[0]; // 80 grades[grades.length - 1]; // 85
How many times have you written [0]
? [arr.length - 1]
? Or worse, [arr.length]
, resulting in an off-by-1 error?
What we mean here is “the first element” and “the last element”. Unfortunately, JavaScript doesn’t provide a method on Array objects to extract the first or last elements.
> grades.first() < TypeError: grades.first is not a function. (In 'grades.first()', 'grades.first' is undefined)
So let’s update the language to clarify that meaning. JavaScript is a prototypal language: There is an Array prototype which all instances of arrays are based on. By adding methods to the Array prototype, we immediately add those methods to every instance of an array.
Array.prototype.first = function() { return(this[0]); } Array.prototype.last = function() { return(this[ this.length - 1 ]); }
Now, we can easily and without fear of off-by-1 errors access the first and last elements:
> grades.first() < 80 > grades.last() < 85
But let’s not stop there… what other functions might it be useful to have? How would you enhance the language to provide those functions?
Any function you write provides an opportunity to make your intentions clearer and to create a domain specific language that allows you to express solutions to problems that interest you more naturally. Use it to your advantage.