Code Showdown: Ruby vs Javascript

Ruby and JavaScript are about to go head to head. Both of these scripting languages are dynamically typed and support object-oriented programming. We’ll examine their differences or similarities across some of their more common features.

Disclaimer: We’re only looking at modern JavaScript ES6 syntax here.

Photo by Pramote Polyamate on 500px

String interpolation

In computer programming, string interpolation is the process of injecting the value of a variable or an expression in a string literal.

In Ruby, this is called, you guessed it, string interpolation.

Ruby:

first_name = "Martin"
last_name = "Riggs"
puts "Hi, I'm #{first_name} #{last_name}."

In Javascript, the same thing can be achieved with template literals.

JavaScript:

const firstName = 'Martin';
const lastName = 'Riggs';
console.log(`Hi, I'm ${firstName} ${lastName}.`);

Methods and functions

Wikipedia explains that, in computer programming, a subroutine is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed.

In different programming languages, a subroutine may be called a procedure, a function, a routine, a method, or a subprogram.

In order to be used, these subroutines need to be first defined and then called. In Ruby, they are known as methods and in JavaScript, they’re called functions.

Ruby:

def full_name(first_name, last_name)
"#{first_name.capitalize} #{last_name.capitalize}"
end
puts full_name("beatrix", "kiddo")

JavaScript:

function fullName(firstName, lastName) {
return `${firstName.capitalize()} ${lastName.capitalize()}`;
};
console.log(fullName("beatrix", "kiddo"));

If you’re running the examples above, you’ve probably noticed that the JavaScript example doesn’t work, but throws an error: Uncaught TypeError: firstName.capitalize is not a function!

This is because JavaScript doesn’t define a capitalize function natively. Ruby has many handy and neat idiomatic methods like #capitalize that are really convenient. To make the above example work, we’ll need to use the prototype chain to monkey patch the JavaScript String object:

String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
}

Blocks

In Ruby, blocks are basically unnamed chunks of code that can be passed onto and called from inside methods. Many of the built-in object methods in Ruby accept blocks and these are a convenient way to tweak the way such methods behave.

Ruby:

def timer
start_time = Time.now
puts "Running block..."

yield
puts "Finished!" end_time = Time.now - start_time "Execution time: #{end_time}"
end
puts timer { (0..10000000).sort }

Hey, JavaScript doesn’t have blocks, so the above implementation is not possible and the comparison is silly! Or is it? JavaScript functions can accept callback functions as arguments and if we think of Ruby blocks as being very much like anonymous methods we can achieve a similar result.

JavaScript:

function timer(callback) {
const startTime = new Date().getTime();
console.log("Running callback...");

callback();
console.log("Finished!"); const endTime = new Date().getTime(); return `Execution time: ${endTime - startTime}`;
};
timer(() => Array.from(Array(10000000).keys()).sort());

Note: Unlike Ruby, JavaScript doesn’t have a built-in Range object. The Array.from(n).keys() above returns an Array from 0 to n.

Idiomatic iterations

Ruby is known for having very nice idiomatic iterators to loop through Arrays (and other Enumerables or iterative structures).

Ruby:

names = ["Tango", "Cash", "Dalton", "Riggs"]
names.each do |name|
puts name
end

With ES6, iterating through an array in JavaScript becomes a breeze:

JavaScript:

const names = ['Tango', 'Cash', 'Dalton', 'Riggs'];
names.forEach( name => console.log(name));

Note: The Javascript forEach function can also access the element’s index. In Ruby, we would use a different iterator for that called each_with_index.

Classes and class inheritance

In Object-Oriented Programming, classes are code templates for creating objects, providing values for state (the object’s properties or attributes) and implementing behaviour (such as getters and setters to read and write such properties or attributes).

Ruby:

class Vehicle
def initialize(name, type)
@name = name
@type = type
end
def name
@name
end
def type
@type
end
end
class Car < Vehicle
def initialize(name)
super(name, 'car')
end
end
diablo = Car.new("Lamborghini")
puts diablo.name
puts diablo.type

JavaScript:

class Vehicle {

constructor (name, type) {
this.name = name;
this.type = type;
}

getName () {
return this.name;
}

getType () {
return this.type;
}

}
class Car extends Vehicle {

constructor (name) {
super(name, 'car');
}
}
const diablo = new Car('Lamborghini');
console.log(diablo.getName());
console.log(diablo.getType());

Note: In the above example, the Ruby Vehicle class would typically be implemented with an attribute reader to create the getter methods for the instance variables. I chose to not use an attribute reader so as to have a more similar look to the JavaScript implementation.

Destructuring

Modern JavaScript introduced this really cool thing called destructuring, where you can assign elements inside arrays or objects to variables with a concise syntax.

JavaScript:

firstName, lastName = 'James Bond'.split();console.log(`My name is ${lastName}, ${firstName} ${lastName}`);

Surely you can’t do this in Ruby!

Ruby:

first_name, last_name = "James Bond".split
puts "My name is #{last_name}, #{first_name} #{last_name}"

Note: While we can destructure arrays in Ruby very much as we do in JavaScript, there’s no Ruby equivalent to directly destructure hashes.

Spread Operator

Modern JavaScript has also introduced the spread operator which allows iterable expressions to be expanded where zero or more arguments or elements are expected.

JavaScript:

function sum(x, y, z) {
return x + y + z;
};
const numbers = [1, 2, 3];
console.log(sum(...numbers);
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a);
console.log(b);
console.log(rest); // rest is an Array!

In Ruby, we have the splat operator for this.

Ruby:

def sum(x, y, z)
x + y + z
end
numbers = [1, 2, 3]
puts sum(*numbers)
a, *rest, b = [10, 20, 30, 40, 50]
puts a
puts b
puts rest # rest is an Array!

Note: You’ve probably noticed that in Ruby *rest is between the other variables. That’s because the splat operator can be placed anywhere. In JavaScript, the spread operator must come last.

Ruby also has the double splat operator ** to do the same thing on hashes. The JavaScript ES2018 specification is introducing the spread operator on objects as well.

Final word

As you’ve probably realized, both languages aren’t so different after all and, with ES6, JavaScript has become increasingly pleasant to write. Sure, JavaScript is the language of the browser and its event loop provides asynchronous behaviour. On the other hand, Ruby has very powerful tools to do metaprogramming and is beloved for its idiomatic syntax. At the end of the end, I think it’s beneficial to learn and know both as often knowledge of one programing language will give you ideas on how to code or tackle a certain problem in another.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Rui Freitas

Rui Freitas

Lead Teacher @ Le Wagon | Web Developer @ Light the Fuse and Run: http://lightthefuse.run/ | Photographer @ Rod Loboz: https://blog.rodloboz.com/