Sometimes the journey from Ruby to JavaScript can feel like diving into a swimming pool of parenthesis and semicolons.
There — I said it.
But JavaScript is really important — and really pervasive. In fact, 78.2% of the top one million websites across the world wide web use JQuery — a JavaScript library and language framework — to render powerful online web applications.
Writing JavaScript as a Rubyist can sometimes burn us as noobie programmers because its syntax is so unforgiving. Remembering to include semicolons and brackets when we are dealing with blocks, returns statements before variable declarations, variable scope (whether local or global) , etcetera and etcetera and etcetera, may feel initially overly-declarative — not to mention frustrating. Don’t worry, n00b, there’s hope.
Let’s look at a few examples.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;; JavaScript ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Behold JavaScript. One look at JavaScript and we see a language abound in semicolons and weird syntax. But no, this is not Brainfuck. Not quite — at least.
Semicolons are abundant in JavaScript because of a process called statement chaining, which only really means executing two statements on one line.
var coolPhrase = “gnik drazil eht ma I"; coolPhrase = coolPhrase.split(“”).reverse().join(“”); coolPhrase = coolPhrase.toUpperCase(); // => “I AM THE LIZARD KING”
Semicolons are also used to delineate and define statements. For example:
var myFace; // variable declaration i = 1000000; // value assignment i = i + 14; // value assignment i++; // value assignment var numOfMyProblems = 99; // value assignment console.log(“I am a genius”); // function call
JavaScript for Rubyists
JavaScript’s framework is incredibly light. This owes itself to it’s unique origins as a functional programming language. Interestingly, JavaScript was originally developed in 10 days in May 1995 by Brendan Eich. Read about the history of JavaScript here.
In Ruby there are many ways to solve a problem because Ruby graciously gives us a bunch of methods to break down a problem. In JavaScript, this is not the case. When I first approached JavaScript, pouring over each function and semi-colon gingerly, I started wondering: “where are all the JavaScript language features?” Where is the .map, the .each, .reduce — for god sakes, the .find!? — allowing for easy and efficient iteration over collections of objects.
The horror when I thought: will I really have to use “for” loops ad infinitum to iterate through problems?
Underscore
Enter Underscore. Underscore is a utility-belt JavaScript library that gives the Rubyist a whole mess of useful functional programming helpers — more than 100, in fact — to keep in your arsenal. From the Underscore API:
“[Underscore] is the answer to the question: “If I sit down in front of a blank HTML page, and want to start being productive immediately, what do I need?” … and the tie to go along with jQuery‘s tux and Backbone‘s suspenders.”
Lets see the brilliance of Underscore in action. (Seriously — prepare to freak out).
Collection Functions
(arrays, objects, array-like objects)
Each in Ruby
Recall using each when working with non-transformative functions. If these functions embody a complex object, this is usually linked to some sort of action. For example: iterating through a list of names (or emails) and interpolating a greeting (or emailing that list in an action mailer).
list_names = ["Holly", "David Bowie", "Lizard King"]
list_names.each {|name| puts “Hello #{name}!”)
=> Hello Holly!
=> Hello David Bowie!
=> Hello Lizard King!
Each in JavaScript
Underscore gives us a pretty sexy each equivalent which we can use to iterate over a list of elements.
_.each(list, iteratee, [context]
Taken in an example:
_.each([1,2,3], function(num){console.log(num);}); // 1 // 2 // 3 [1, 2, 3]
Super cool.
Map in Ruby
Recall using map in Ruby for transformative functions.
a = [1,2,3] irb > a.map {|num| num * num } => [1, 4, 9]
Cool beans! We know and love map in Ruby when iterating through collections of objects.
Map in JavaScript
Underscore syntax of map is very similar to its Ruby counterpart.
_.map(list, iteratee, [context])
Let’s look at an example.
a = [1,2,3] _.map([1,2,3], function(num){ return num * 9;}); // [9, 18, 27]
Nonsense-amounts of awesome.
Working With Arrays
(Lists of Elements and Objects)
First in Ruby
We know first as a powerful Ruby method which returns or plucks the first element [with index 0] of an array. For example:
gross_words = ["moist", "bumpkin", yourMom"] gross_words.first => "moist"
First in JavaScript
Surprise, surprise. First in JavaScript is very similar.
_.first([5, 4, 3, 2, 1]);
=> 5
Identity Functions
(Uncovering the Status of Objects)
Identity functions allow us to uncover the status of objects. This is important in programming — and especially in JavaScript — because objects can be conceptually different if they are nil, NaN, or null. Studying the Underscore API I was struck by the applicability of these functions in JavaScript:
isNaN
syntax: _.isNaN(object)
Returns true if object is NaN
_.isNaN(NaN); => true isNaN(undefined); => true _.isNaN(undefined); => false
isNull
syntax: _.isNull(object)
Returns true if the value of object is null.
_.isNull(null); => true _.isNull(undefined); => false
isUndefined
syntax: _.isUndefined(value)
Returns true if value is undefined.
_.isUndefined(window.missingVariable); => true
Resources