This document is useful to developers who know either JavaScript or Ruby and want to learn the other language. Note that the code provided for comparison may not have the exact same behaviour. Edge cases are not covered extensively.
- JavaScript vs Ruby
// JavaScript
node
# Ruby
irb
// JavaScript
var x = 10
let day = 'today'
# Ruby
x = 10
day = 'today'
// JavaScript
const PI = 3.1415
# Ruby
PI = 3.1415.freeze
// JavaScript
x = 10
y = 20
z = x + y
# Ruby
x = 10
y = 20
z = x + y
// JavaScript
42 == '42' // true
42 === '42' // false
42 === 42 // true
'color' == 'color' // true
'color' === 'color' // true
'color' === 'colour' // false
[3, 5, 7] === [3, 5, 7] // false
Note: For JavaScript, using ===
is preferred.
# Ruby
1 == '1' # false
1 == 1 # true
'color' == 'color' # true
'color' == 'colour' # false
[3, 5, 7] == [3, 5, 7] # true
// JavaScript
Math.random() // Returns floating value [0, 1)
# Ruby
rand(0 .. 1.0) # Returns floating value [0, 1.0]
// JavaScript
if (100 > 4) {
console.log('greater');
}
# Ruby
if 100 > 4
print 'greater'
end
# OR
print 'greater' if 100 > 4
// JavaScript
if (2 > 7) {
console.log('2 > 7');
} else {
console.log('2 < 7')
}
# Ruby
if 2 < 7
print '2 < 7'
else
print '2 > 7'
end
// JavaScript
if (2 > 7) {
console.log('2 > 7');
} else if (2 < 7) {
console.log('2 < 7')
} else {
console.log('2 = 7')
}
# Ruby
if 2 < 7
print '2 < 7'
elsif
print '2 > 7'
else
print '2 = 7'
end
// JavaScript
const a = 1;
switch (a) {
case 0:
console.log("It's zero")
break;
case 1:
console.log("It's one")
break;
default:
console.log("It's something else")
break;
}
# Ruby
a = 1
puts case a
when 0
"It's zero"
when 1
"It's one"
else
"It's something else"
end
# prints: "It's one"
// JavaScript
var arr = [1, 2, 3, 4, 5]
# Ruby
arr = [1, 2, 3, 4, 5]
// JavaScript
var arr = [1, 2, 3, 4, 5]
arr.length // 5
# Ruby
arr = [1, 2, 3, 4, 5]
arr.length # 5
# Alernative
arr.length() # 5
// JavaScript
var arr = [1, 2, 3, 4, 5]
arr.push(6)
# Ruby
arr = [1, 2, 3, 4, 5]
arr.push(6)
arr.push 7
arr << 8
// JavaScript
var arr = [2, 3, 4, 5]
arr.unshift(1)
# Ruby
arr = [2, 3, 4, 5]
arr.unshift(1)
// JavaScript
var arr = ['red', 'blue', 'green']
arr.includes('blue') // true
arr.includes('yellow') // false
# Ruby
arr = ['red', 'blue', 'green']
arr.includes?('blue') # true
arr.includes?('yellow') # false
// JavaScript
var arr = [1, 2, 3, 4, 5]
arr.map(function (n) { return n * n; });
// OR
arr.map(function square(n) { return n * n; });
// OR
const square = n => n * n;
arr.map(square); // Will only work for functions accepting one argument
// OR
arr.map(n => square(n))
// OR
arr.map(n => n * n); // Arrow function
// All return: [1, 4, 9, 16, 25]
# Ruby
arr = [1, 2, 3, 4, 5]
arr.map { |n| n * n }
# OR
def square(n)
return n * n
end
arr.map { |n| square(n) }
# OR
arr.map do |n|
return n * n
end
# All return: [1, 4, 9, 16, 25]
// JavaScript
var arr = [1, 2, 3, 4, 5]
arr.forEach(function (n) { console.log(n * n); });
// OR
arr.forEach(function square(n) {
console.log(n * n);
});
// OR
const print = n => console.log(n * n);
arr.forEach(print); // Will only work for functions accepting one argument
// OR
arr.forEach(n => print(n))
// OR
arr.forEach(n => {
console.log(n * n);
}); // Arrow function
// All print:
// 1
// 4
// 9
// 16
// 25
# Ruby
arr = [1, 2, 3, 4, 5]
arr.each { |n| print "#{n * n}," }
# OR
arr.each do |n|
print "#{n * n},"
end
# All print: 1,4,9,16,25,
// JavaScript
var planet = { name: 'Mercury', index: 0 }
planet.name // 'Mercury'
planet['name'] // 'Mercury'
In JavaScript, an object can be considered a hash.
# Ruby
planet = { name: 'Mercury', index: 0 }
planet[:name] # 'Mercury'
planet['name'] # nil
# Alternative
planet = { :name => 'Earth', :index => 2 }
planet[:index] # 2
planet['index'] # nil
# With strings
planet = { 'name' => 'Earth', 'index' => 2 }
planet['name'] # Earth
planet[:name] # nil
In Ruby:
-
In
{ name: 'Mercury' }
,name
is a Symbol. -
In
{ 'name' => 'Earth' }
,name
is a String.
Good resource for learning more about hashes in Ruby: http://ruby-for-beginners.rubymonstas.org/built_in_classes/hashes.html
// JavaScript
var planet = { name: 'Mercury', index: 0 }
'name' in planet // true, checks in prototype chain as well
// Alternative
planet.hasOwnProperty('name') // true, checks own properties only
// Alternative 2
Object.prototype.hasOwnProperty.call(planet, 'name') // true, checks own properties only
# Ruby
planet = { name: 'Mercury', index: 0 }
planet.key?(:name) # true
planet.key?('name') # false
planet = { 'name' => 'Mercury', 'index' => 0 }
planet.key?(:name) # false
planet.key?('name') # true
// JavaScript
var planet = { name: 'Mercury', index: 0 }
delete planet.name
// Alternative
delete planet['name']
# Ruby
planet = { name: 'Mercury', index: 0 }
planet.delete(:name) # Works
planet.delete('name') # Doesn't work!
planet = { "name" => 'Mercury', "index" => 0 }
planet.delete('name') # Works
planet.delete(:name) # Doesn't work!
// JavaScript
var httpResponse = { status_code: 404 }
var key = 'status_code';
httpResponse[key] // 400
# Ruby
http_response = { status_code: 404 }
key = 'status_code';
http_response[key] # 400
// JavaScript
var httpResponse = { status_code: 404 }
httpResponse.data // undefined
httpResponse.data.name // Throws an error
httpResponse.data?.name // undefined
# Ruby
http_response = { status_code: 404 }
http_response[:data] # Throws an error
http_response.fetch(:data, nil) # nil
http_response.fetch(:data, nil).fetch(:name, nil) # Throws an error
http_response.fetch(:data, nil)&.fetch(:name, nil) # nil
// JavaScript
var old = { name: 'Marz' };
var updated = { name: 'Mars', index: 4 };
Object.assign(old, updated); // Returns { name: 'Mars', index: 4 }
old // { name: 'Mars', index: 4 }
# Ruby
old = { 'name' => 'Marz' }
updated = { 'name' => 'Mars', 'index' => 4 }
old.merge!(updated) # Returns {:name=>"Mars", :index=>4}
old # {:name=>"Mars", :index=>4}
// JavaScript
var old = { name: 'Marz' };
var updated = { name: 'Mars', index: 4 };
Object.assign({}, old, updated); // Returns { name: 'Mars', index: 4 }
old // { name: 'Marz' }
# Ruby
old = { 'name' => 'Marz' }
updated = { 'name' => 'Mars', 'index' => 4 }
old.merge(updated) # Returns {"name"=>"Mars", "index"=>4}
old # {'name' => 'Marz'}
// JavaScript
var array = [['name', 'Mars'], ['index', 4], ['color', 'red']];
Object.fromEntries(array); // { name: 'Mars', index: 4, color: red }
# Ruby
array = [['name', 'Mars'], ['index', 4], ['color', 'red']]
Hash(array); # {"name"=>"Mars", "index"=>4, "color"=>"red"}
// JavaScript
planet = JSON.parse('{"name": "Mercury", "index": 0}')
planet.name // Mercury
# Ruby
require 'json'
planet = JSON.parse('{"name": "Mercury", "index": 0}')
planet[:name] # nil
planet['name'] # Mercury
# Allow accessing with key names
planet = JSON.parse('{"name": "Mercury", "index": 0}')
planet['name'] # Mercury
planet = JSON.parse('{"name": "Mercury", "index": 0}', symbolize_names: true)
planet[:name] # Mercury
// JavaScript
JSON.stringify({ name: 'Mercury' }) // "{\"name\":\"Mercury\"}"
# Ruby
require 'json'
JSON[{ name: 'Mercury' }] # "{\"name\":\"Mercury\"}"
# Alternative
{ name: 'Mercury' }.to_json # "{\"name\":\"Mercury\"}"
// JavaScript
function power(base = 2, exponent = 1) {
return x ** y;
}
power(3, 2) // 9
power(2) // 2
power() // 2
# Ruby
def power(base = 2, exponent = 1)
base ** exponent
end
power(3, 2) # 9
power(3) # 9
power()
# Alternative
power 3, 2 # 9
power 3 # 9
power # 9
Note: In Ruby, the value of last statement of a function's body is returned by default. Writing return
is optional.
// JavaScript
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
let r = new Rectange(5, 20);
r.getArea() // 100
Note: In JavaScript, r.width
is accessible from outside. In order to make the variable private, you need to use private fields (not widely supported at the time of writing this).
# Ruby
class Rectangle
def initialize(width, height)
@width = width
@height = height
end
def self.get_area
return @width * @height
end
end
r = Rectangle.new(5, 20)
r.get_area # 100
Note: In the above Ruby example, method get_area can also be declared without self.
. Using self.
allows us to access a method named get_area
inside the class which is not a part of the Rectangle class.
Note: In Ruby, r.width
is not accessible from outside. In order to make the variable public, you need to write attr_reader :width, :height
for read access and attr_writer :width, :height
for write access.
class HTTPResponse {
static OK = 200; // case-insensitive
isSuccess() {
return this.statusCode === HTTPResponse.OK;
}
}
let response = new HTTPResponse
response.isSuccess() // false
class HTTPResponse
OK = 200
def is_success
@status_code == HTTPResponse::OK
end
end
response = HTTPResponse.new
response.is_success # false
// JavaScript
Number('1') // Returns 1
Number('3.1415') // Returns 3.1415
Number(null) // Returns 0
Number(undefined) // Returns NaN
Number('hello') // Returns NaN
'one' + 1 // Returns 'one1'
# Ruby
'1'.to_i # Returns 1
Integer('1') # Returns 1
'3.1415'.to_i # Returns 3
'3.1415'.to_f # Returns 3.1415
Float('3.1415') # Returns 3.1415
Float('hello') # Throws error
nil.to_i # Returns 0
'hello'.to_i # Returns 0
Integer('hello') # Throws error
'one' + 1 # Throws error
'one' + 1.to_s # Returns "one1"
// JavaScript
['h', 'e', 'l', 'l', 'o'].join('') // 'hello'
'hello'.split('') // ['h', 'e', 'l', 'l', 'o']
['rock', 'paper', 'scizzor'].join(', ') // 'rock, paper, scizzor'
'rock paper scizzor'.split(' ') // ['rock', 'paper', 'scizzor']
# Ruby
['h', 'e', 'l', 'l', 'o'].join('') # 'hello'
'hello'.split('') # ['h', 'e', 'l', 'l', 'o']
['rock', 'paper', 'scizzor'].join(', ') # 'rock, paper, scizzor'
'rock paper scizzor'.split(' ') # ['rock', 'paper', 'scizzor']
%w(rock paper scizzor) # ['rock', 'paper', 'scizzor']