Ruby vs. JavaScript — Exploring Datatypes and Mutability
This will be a series of articles comparing Ruby and JavaScript for beginning to intermediate programmers. I hope you learn something along the way!
Contents
- Defining terms
- Ruby vs. JavaScript as a first language
- Datatypes
- Mutability
- Pass-by-reference vs. Pass-by-value
Both Ruby and JavaScript are great languages to learn for a beginner.
Some terms you need to know before we start:
Variable: pointer or name given to a certain value in memory. So that value doesn’t have to be re-typed every time it is used.
full_name = 'Hermonie Granger'
Object: data-structure made up of key-value pairs. Keys are the unique identifier for some value.
headmaster = {name: 'Albus', age: 'over 100?'}
- name and age are the keys.
Classes: blueprints for any objects that are created using that class
- Blueprints as in any objects created will have the specified properties and methods dictated by the class
- objects created using a class are called instances
# Ruby Class # # Defining a classclass Wizard def initialize(name, house) @name = name @house = house endend
# Creating an instance of Wizard (a Wizard Object)hermonie = Wizard.new('hermonie', 'gryffindor')
The Wizard class dictates that any created instances will have the properties name and house
- These are specified when the instance is created (using the
newclass method)
This will be further elaborated on in a further article. This is just so you’re aware of the concepts.
Methods: reusable code that can be customized using variables (also called functions or procedures).
# Ruby Code
# Defining a method that shows a string (put string)def introduce(name) puts nameend
# Calling introduce and passing a stringintroduce('Draco')# => 'Draco'
//precede lines of code that are commented out JavaScript (JS)
console.logis a method used to print values to the console (JS)
#precedes lines of code that are commend out in Ruby
=>is called a hash-rocket and represents what is returned from lines of code(when used in Ruby comments)
Comparison
Ruby
Ruby is designed with the idea that programming should be enjoyable.
- It’s an Object-oriented programming language which means that code is structured into objects and those objects communicate with each other. It is a very popular form of programming that can lead to organized, compartmentalized, and reusable code.
- It’s syntax is clear, easy to read, and intuitive.
gets gets a string input, puts puts a string, repeating an action is simple (looping).
10.times do |n| puts "number is " + nend
- 10 times: put the string “number is ” with the current number in the loop.
What many beginners are taught in JavaScript:
for (var i = 0; i < 10; i++) { console.log(i)}
- Once you understand what all that means — it’s simple. It can seem very cryptic at first though.
JavaScript
The default language of the web and according to the annual Stack Overflow survey from 2017 — the most popular.
Stack Overflow Developer Survey 2017
- Because of it’s popularity there are many free resources to learning JavaScript.
- JavaScript has become more object-oriented in recent years but is actually a prototypal-based language which can create code that is simpler and less interdependent than OOP.
- If you don’t know what any of that means, no worries — it all comes with time.
I would recommend JavaScript for the job opportunities but really you can’t go wrong learning either. Learning the fundamental programming concepts is more important than the language.
- Also the more languages you learn, the better programmer you will become. Do stay consistent with one though and learn it in depth before moving on to another. Many recommend learning a stack (LAMP, MEAN, MERN) or a group of languages if you’re doing web development.
This article will give you a starting point for navigating all the needed technologies for back-end or front-end
The 2018 Web Developer Roadmap — codeburst
With that intro aside, let’s start with how data is stored in both languages
Datatypes
A data type is simply a category that tells the compiler (what turns your code into machine code) how to interpret the data.
- Ruby and JavaScript are dynamically typed languages. This means that variables don’t have an explicit type and can be assigned and reassigned any type of value.
- The data type of the variable is determined by whatever type is the current value of that variable
As opposed to statically-typed languages where type is explicitly stated for each variable and reassigning to a different value type leads to an error.
In the following — a variable is declared and assigned and reassigned data of different types
// Javascript //// String valuevar orphan = 'Harry'// Number valueorphan = 11;// Object valueorphan = {knownAs: 'The boy who lived', favoriteSport: 'quidditch'};# Ruby ## String valuedobby = 'house elf'# Hash valuedobby = {'warning' => 'Harry Potter must not go back to hogwarts!'}# FalseClass value (Boolean)dobby = false
the data type of orphan or dobby does not need to be explicitly stated beforehand and is not permanently set once the variable is defined
Both languages are flexible in what values variables can be assigned but have key differences in how the values themselves are stored in the computer’s memory.
In Ruby — everything is an Object and each data type is an instance of a class
- The piece of data is said to be an object of that class
4is anIntegerobject- The data itself is the object (not the variable)
In JavaScript — some data-types are Primitives and the rest are Objects
Types found in both languages
- String
- Array
- Symbol
Ruby Types
- NilClass
- TrueClass
- FalseClass
- Hash
- Float (Numbers with decimal)
- Integer (Whole numbers)
JavaScript Types
Primitives
- Boolean
- Null
- Undefined
- Number (Represents both floating point and integer numbers)
Null and Undefined both mean without value. However, Undefined should not be used by the programmer - only by the JS engine. Use Null instead.
Objects
- Functions
- Maps
- Object
Determining Datatype
Ruby
Object.class
'seeker'.class
# => String{name: 'Ron'}.class
# => Hash9.75.class
# => Float
JavaScript
typeof
console.log(typeof 9.75);
// "number"console.log(typeof 'Expecto Patronum');
// "string"console.log(typeof true);
// "boolean"
Mutability (How data is stored)
In JavaScript — primitive datatypes are stored differently from object datatypes
In Ruby — everything is an object but some datatypes are still stored differently than others
You may ask, why do I need to know this?
When changing or moving values around in your program. It is important to understand what values are actually being copied or changed
- Understanding how information is managed by a language will help you understand the state of your program.
- In other words — the data and which functions are changing it
Every value in a program has a place in memory
If you want a more in depth explanation and history of the concepts of place and value in programming, I highly recommend this talk by Rich Hickey (the creator of Clojure)
The value in that place can either be updated or it cannot
- A mutable value is one that can be modified
- An immutable value is one that cannot be modified
In Ruby the only data types that are immutable by default
- TrueClass, FalseClass, nil
- Numeric
- Symbol
In JavaScript that only datatypes that are immutable are primitives
How these values are copied or passed to functions depends on the datatype and whether it is considered immutable
Pass-by-reference vs Pass-by-value
Copies by-reference means that an additional pointer is being created to the same place in memory
- Two variables with the exact same value
Copies by-value means that an additional pointer is being created with a new location in memory
- Two variables with different values
Ruby
In ruby
object_idreturns the memory address of that object
# Immutable values ## Copying a value by-referencehorcruxes = 6souls = horcruxeshorcruxes.object_id == souls.object_id# => truelord_voldy = falsetom_riddle = lord_voldylord_voldy.object_id == tom_riddle.object_id# => true
In the previous examples — there is only one value (type Integer and FalseClass) and “copies” are made by creating another pointer to that value
When copying mutable values in Ruby — the behavior is similar to immutable values
- Both variables point to the same value. If the value is modified but not reassigned the changed value is visible in both variables.
# Creating a copy by-reference of a mutable valuemother = 'Lily Evans'gryffindor = mother# Concat adds a string to the called stringmother.concat(' - Potter')puts gryffindor
# => 'Lily Evans - Potter'mother.object_id == gryffindor.object_id
# => true
Both mother and gryffindor point to the same string in memory and thus mutating the value using one variable affects both.
With reassignment however
mother = 'Ginny Weasley'puts gryffindor
# => 'Lily Evans - Potter'mother.object_id == gryffindor.object_id
# => false
- Assigning the original to a new value creates a new value in memory — and the copy continues to point to the original value
Passing to a function
- Immutable types are passed by value and mutable types are passed by reference
- This isn’t technically correct. Ruby appears to behave this way — for immutable values it is actually passing by reference value. This is all you need to know though. If you want to know more — Launch School is a great resource on all things Ruby.
- Object Passing in Ruby — by Reference or by Value?
# Mutable values #wandmaker = 'Garrick Ollivander'def add_house(name) # Is this a copy made only for the execution of this method? name.concat(' - Ravenclaw') puts name # memory address for name puts name.object_idendadd_house(wandmaker) # Testing whether original value was changed puts wandmaker puts wandmaker.object_idend
# Garrick Ollivander - Ravenclaw# 70349890968900# Garrick Ollivander - Ravenclaw# 70349890968900
The value for wandmaker was permanently modified outside of the method add_house and the object_id methods show that the memory address is the same inside and outside the method.
- Ruby, for mutable values, is pass by-reference — an additional pointer is being created to the same place in memory. That value is being altered.
For reassignment however — the behavior is different
tonks = 'nymphadora tonks'def new_capitalize(name) capital_name = name.capitalize puts capital_name puts capital_name.object_idendnew_capitalize(tonks)puts tonksputs tonks.object_id# Nymphadora tonks# 70314315512820# nymphadora tonks# 70314315512900
With reassignment — the original value remains the same and the memory addresses are different.
- Reassignment creates a new place in memory. Modification changes the current place in memory.
JavaScript
In JavaScript — objects are mutable and only primitive types are immutable
There is no way to find the memory address of a value in JavaScript (that I have been able to find) but for primitives it appears to be copy-by-value and for objects by-reference
Copy by-value — primitive
// String is a primitive and thus immutablelet patronus_ron = 'Jack Russel Terrier';// Creating a copy by-valuelet patronus_dog = patronus_ron;// Concatenating a string to the originalpatronus_ron += ' + Otter';// Does not affect the copyconsole.log(patronus_dog) // 'Jack Russel Terrier'
Because primitive types are immutable - attempting to change the value seems to create a new place in memory rather than mutate the original
Copy by-reference — object
// Objects are mutable, copies are by-referencelet severus = {lastName: 'Snape', proffesion: 'Potions Master'};// Creating a 'copy' (additional pointer)let headmaster = severus;// Changing the originalseverus.patronus = 'doe';// Mutates the copyconsole.log(headmaster);// {"lastName":"Snape","proffesion":"Potions Master","patronus":"doe"}
- Both variables are pointers to the same object in memory — changing the value changes all references
Passing works the same way as copying
Primitive: by-value
// String type
yearsInAzkaban = 12;function add(number) { number += 2; console.log(number);}add(yearsInAzkaban);// 14console.log(yearsInAzkaban);// 12
Object: by-reference
let deathEater = {name: 'Bellatrix Lestrange'};function addPureBlood(wizard) { wizard.bloodStatus = 'Pure'; console.log(wizard);}addPureBlood(deathEater);console.log(deathEater);// Both the orginal and copy point to the same value// {name:"Bellatrix Lestrange", bloodStatus:"Pure"}
Ruby and JavaScript really aren’t too different when it comes to datatypes and mutability. If I missed anything or something was left unclear, please leave a comment below.
Thanks for reading! Take care.
