This page provides a comparison between the JavaScript and Scala programming languages. It’s intended for programmers who know JavaScript and want to learn about Scala, specifically by seeing examples of how JavaScript language features compare to Scala.
Overview
This section provides a relatively brief introduction and summary of the sections that follow. It presents the similarities and differences between JavaScript and Scala at a high level, and then introduces the differences you’ll experience every day as you write code.
High-level similarities
At a high level, Scala shares these similarities with JavaScript:
- Both are considered high-level programming languages, where you don’t have to concern yourself with low-level concepts like pointers and manual memory management
- Both have a relatively simple, concise syntax
- Both support a C/C++/Java style curly-brace syntax for writing methods and other block of code
- Both include features (like classes) for object-oriented programming (OOP)
- Both include features (like lambdas) for functional programming (FP)
- JavaScript runs in the browser and other environments like Node.js. The Scala.js flavor of Scala targets JavaScript and Scala programs can thus run in the same environments.
- Developers write server-side applications in JavaScript and Scala using Node.js; projects like the Play Framework also let you write server-side applications in Scala
- Both languages have similar
if
statements,while
loops, andfor
loops - Starting at this Scala.js page, you’ll find dozens of libraries to support React, Angular, jQuery, and many other JavaScript and Scala libraries
- JavaScript objects are mutable; Scala objects can be mutable when writing in an imperative style
- Both JavaScript and Scala support promises as a way of handling the result of asynchronous computations (Scala concurrency uses futures and promises)
High-level differences
Also at a high level, some of the differences between JavaScript and Scala are:
- JavaScript is dynamically typed, and Scala is statically typed
- Although Scala is statically typed, features like type inference make it feel like a dynamic language (as you’ll see in the examples that follow)
- Scala idioms favor immutability by default: you’re encouraged to use immutable variables and immutable collections
- Scala has a concise but readable syntax; we call it expressive
- Scala is a pure OOP language, so every object is an instance of a class, and symbols like
+
and+=
that look like operators are really methods; this means that you can create your own methods that work as operators - As a pure OOP language and a pure FP language, Scala encourages a fusion of OOP and FP, with functions for the logic and immutable objects for modularity
- Scala has state of the art, third-party, open source functional programming libraries
- Everything in Scala is an expression: constructs like
if
statements,for
loops,match
expressions, and eventry
/catch
expressions all have return values - The Scala Native project lets you write “systems” level code, and also compiles to native executables
Programming level differences
At a lower level, these are some of the differences you’ll see every day when writing code:
- Scala variables and parameters are defined with
val
(immutable, like a JavaScriptconst
) orvar
(mutable, like a JavaScriptvar
orlet
) - Scala does not use semi-colons at the end of lines
- Scala is statically-typed, though in many situations you don’t need to declare the type
- Scala uses traits as interfaces and to create mixins
- In addition to simple
for
loops, Scala has powerfulfor
comprehensions that yield results based on your algorithms - Pattern matching and
match
expressions will change the way you write code - Scala’s contextual abstractions and term inference provide a collection of features:
- Extension methods let you add new functionality to closed classes without breaking modularity, by being available only in specific scopes (as opposed to monkey-patching, which can pollute other areas of the code)
- Given instances let you define terms that the compiler can use to synthesize code for you
- Type safety and multiversal equality let you limit equality comparisons—at compile time—to only those comparisons that make sense
- Thanks to features like by-name parameters, infix notation, optional parentheses, extension methods, and higher-order functions, you can create your own “control structures” and DSLs
- Many other goodies that you can read about throughout this book: case classes, companion classes and objects, macros, union and intersection types, multiple parameter lists, named arguments, and more
Variables and Types
Comments
//
|
//
|
Mutable variables
let // now preferred for mutable
|
var // used for mutable variables
|
Immutable values
const
|
val
|
The rule of thumb in Scala is to declare variables using val
, unless there’s a specific reason you need a mutable variable.
Naming standards
JavaScript and Scala generally use the same CamelCase naming standards.
Variables are named like myVariableName
, methods are named like lastIndexOf
, and classes and object are named like Animal
and PrintedBook
.
Strings
Many uses of strings are similar in JavaScript and Scala, though Scala only uses double-quotes for simple strings, and triple-quotes for multiline strings.
String basics
// use single- or double-quotes
|
// use only double-quotes
|
Interpolation
let name = 'Joe';
|
val name = "Joe"
|
Multiline strings with interpolation
let name = "joe";
|
val name = "Martin Odersky"
|
JavaScript and Scala also have similar methods to work with strings, including charAt
, concat
, indexOf
, and many more.
Escape characters like \n
, \f
, \t
are also the same in both languages.
Numbers and arithmetic
Numeric operators are similar between JavaScript and Scala.
The biggest difference is that Scala doesn’t offer ++
and --
operators.
Numeric operators:
let x = 1;
|
val x = 1
|
Increment and decrement:
i++;
|
i += 1;
|
Perhaps the biggest difference is that “operators” like +
and -
are really methods in Scala, not operators.
Scala numbers also have these related methods:
var a = 2
a *= 2 // 4
a /= 2 // 2
Scala’s Double
type most closely corresponds to JavaScript’s default number
type,
Int
represents signed 32-bit integer values, and BigInt
corresponds to JavaScript’s bigint
.
These are Scala Int
and Double
values.
Notice that the type doesn’t have to be explicitly declared:
val i = 1 // Int
val d = 1.1 // Double
You can also use other numeric types as needed:
val a: Byte = 0 // Byte = 0
val a: Double = 0 // Double = 0.0
val a: Float = 0 // Float = 0.0
val a: Int = 0 // Int = 0
val a: Long = 0 // Long = 0
val a: Short = 0 // Short = 0
val x = BigInt(1_234_456_789)
val y = BigDecimal(1_234_456.890)
Boolean values
Both languages use true
and false
for boolean values:
let a = true;
|
val a = true
|
Dates
Dates are another commonly used type in both languages.
Get the current date:
let d = new Date();
|
// different ways to get the current date and time
|
Specify a different date:
let d = Date(2020, 1, 21, 1, 0, 0, 0);
|
val d = LocalDate.of(2020, 1, 21)
|
In this case, Scala uses the date and time classes that come with Java. Many date/time methods are similar between JavaScript and Scala. See the java.time package for more details.
Functions
In both JavaScript and Scala, functions are objects, so their functionality is similar, but their syntax and terminology is a little different.
Named functions, one line:
function add(a, b) {
|
// technically this is a method, not a function
|
Named functions, multiline:
function addAndDouble(a, b) {
|
def addAndDouble(a: Int, b: Int): Int =
|
In Scala, showing the Int
return type is optional.
It’s not shown in the add
example and is shown in the addAndDouble
example, so you can see both approaches.
Anonymous functions
Both JavaScript and Scala let you define anonymous functions, which you can pass into other functions and methods.
Arrow and anonymous functions
// arrow function
|
// a function (an anonymous function assigned to a variable)
|
In Scala you rarely define a function using the first syntax shown. Instead, you often define anonymous functions right at the point of use. Many collections methods are higher-order functions and accept function parameters, so you write code like this:
// map method, long form
List(1,2,3).map(i => i * 10) // List(10,20,30)
// map, short form (which is more commonly used)
List(1,2,3).map(_ * 10) // List(10,20,30)
// filter, short form
List(1,2,3).filter(_ < 3) // List(1,2)
// filter and then map
List(1,2,3,4,5).filter(_ < 3).map(_ * 10) // List(10, 20)
Classes
Scala has both classes and case classes. A class is similar to a JavaScript class, and is generally intended for use in OOP style applications (though they can also be used in FP code), and case classes have additional features that make them very useful in FP style applications.
The following example shows how to create several types as enumerations, and then defines an OOP-style Pizza
class.
At the end, a Pizza
instance is created and used:
// create some enumerations that the Pizza class will use
enum CrustSize:
case Small, Medium, Large
enum CrustType:
case Thin, Thick, Regular
enum Topping:
case Cheese, Pepperoni, BlackOlives, GreenOlives, Onions
// import those enumerations and the ArrayBuffer,
// so the Pizza class can use them
import CrustSize.*
import CrustType.*
import Topping.*
import scala.collection.mutable.ArrayBuffer
// define an OOP style Pizza class
class Pizza(
var crustSize: CrustSize,
var crustType: CrustType
):
private val toppings = ArrayBuffer[Topping]()
def addTopping(t: Topping): Unit =
toppings += t
def removeTopping(t: Topping): Unit =
toppings -= t
def removeAllToppings(): Unit =
toppings.clear()
override def toString(): String =
s"""
|Pizza:
| Crust Size: ${crustSize}
| Crust Type: ${crustType}
| Toppings: ${toppings}
""".stripMargin
end Pizza
// create a Pizza instance
val p = Pizza(Small, Thin)
// change the crust
p.crustSize = Large
p.crustType = Thick
// add and remove toppings
p.addTopping(Cheese)
p.addTopping(Pepperoni)
p.addTopping(BlackOlives)
p.removeTopping(Pepperoni)
// print the pizza, which uses its `toString` method
println(p)
Interfaces, traits, and inheritance
Scala uses traits as interfaces, and also to create mixins. Traits can have both abstract and concrete members, including methods and fields.
This example shows how to define two traits, create a class that extends and implements those traits, and then create and use an instance of that class:
trait HasLegs:
def numLegs: Int
def walk(): Unit
def stop() = println("Stopped walking")
trait HasTail:
def wagTail(): Unit
def stopTail(): Unit
class Dog(var name: String) extends HasLegs, HasTail:
val numLegs = 4
def walk() = println("I’m walking")
def wagTail() = println("⎞⎜⎛ ⎞⎜⎛")
def stopTail() = println("Tail is stopped")
override def toString = s"$name is a Dog"
// create a Dog instance
val d = Dog("Rover")
// use the class’s attributes and behaviors
println(d.numLegs) // 4
d.wagTail() // "⎞⎜⎛ ⎞⎜⎛"
d.walk() // "I’m walking"
Control Structures
Except for the use of ===
and !==
in JavaScript, comparison and logical operators are almost identical in JavaScript and Scala.
Comparison operators
JavaScript | Scala |
---|---|
== |
== |
=== |
== |
!= |
!= |
!== |
!= |
> |
> |
< |
< |
>= |
>= |
<= |
<= |
Logical operators
JavaScript | Scala |
---|---|
&&
|
&&
|
if/then/else expressions
JavaScript and Scala if/then/else statements are similar. In Scala 2 they were almost identical, but with Scala 3, curly braces are no longer necessary (though they can still be used).
if
statement, one line:
if (x == 1) { console.log(1); }
|
if x == 1 then println(x)
|
if
statement, multiline:
if (x == 1) {
|
if x == 1 then
|
if, else if, else:
if (x < 0) {
|
if x < 0 then
|
Returning a value from if
:
JavaScript uses a ternary operator, and Scala uses its if
expression as usual:
let minVal = a < b ? a : b;
|
val minValue = if a < b then a else b
|
if
as the body of a method:
Scala methods tend to be very short, and you can easily use if
as the body of a method:
function min(a, b) {
|
def min(a: Int, b: Int): Int =
|
In Scala 3 you can still use the “curly brace” style, if you prefer. For instance, you can write an if/else-if/else expression like this:
if (i == 0) {
println(0)
} else if (i == 1) {
println(1)
} else {
println("other")
}
Loops
Both JavaScript and Scala have while
loops and for
loops.
Scala used to have do/while loops, but they have been removed from the language.
while
loop:
let i = 0;
|
var i = 0;
|
The Scala code can also be written like this, if you prefer:
var i = 0
while (i < 3) {
println(i)
i += 1
}
The following examples show for
loops in JavaScript and Scala.
They assume that you have these collections to work with:
// JavaScript
let nums = [1, 2, 3];
// Scala
val nums = List(1, 2, 3)
for
loop, single line
// newer syntax
|
// preferred
|
for
loop, multiple lines in the body
// preferred
|
// preferred
|
Multiple generators in a for
loop
let str = "ab";
|
for
|
Generator with guards
A guard is a name for an if
expression inside a for
expression.
for (let i = 0; i < 10; i++) {
|
for
|
for
comprehension
A for
comprehension is a for
loop that uses yield
to return (yield) a value. They’re used often in Scala.
N/A |
val list =
|
switch & match
Where JavaScript has switch
statements, Scala has match
expressions.
Like everything else in Scala, these truly are expressions, meaning they return a result:
val day = 1
// later in the code ...
val monthAsString = day match
case 1 => "January"
case 2 => "February"
case _ => "Other"
match
expressions can handle multiple matches in each case
statement:
val numAsString = i match
case 1 | 3 | 5 | 7 | 9 => "odd"
case 2 | 4 | 6 | 8 | 10 => "even"
case _ => "too big"
They can also be used as the body of a method:
def isTruthy(a: Matchable) = a match
case 0 | "" => false
case _ => true
def isPerson(x: Matchable): Boolean = x match
case p: Person => true
case _ => false
match
expressions have many other pattern-matching options.
Collections classes
Scala has different collections classes for different needs.
Common immutable sequences are:
List
Vector
Common mutable sequences are:
Array
ArrayBuffer
Scala also has mutable and immutable Maps and Sets.
This is how you create the common Scala collection types:
val strings = List("a", "b", "c")
val strings = Vector("a", "b", "c")
val strings = ArrayBuffer("a", "b", "c")
val set = Set("a", "b", "a") // result: Set("a", "b")
val map = Map(
"a" -> 1,
"b" -> 2,
"c" -> 3
)
Methods on collections
The following examples show many different ways to work with Scala collections.
Populating lists:
// to, until
(1 to 5).toList // List(1, 2, 3, 4, 5)
(1 until 5).toList // List(1, 2, 3, 4)
(1 to 10 by 2).toList // List(1, 3, 5, 7, 9)
(1 until 10 by 2).toList // List(1, 3, 5, 7, 9)
(1 to 10).by(2).toList // List(1, 3, 5, 7, 9)
('d' to 'h').toList // List(d, e, f, g, h)
('d' until 'h').toList // List(d, e, f, g)
('a' to 'f').by(2).toList // List(a, c, e)
// range method
List.range(1, 3) // List(1, 2)
List.range(1, 6, 2) // List(1, 3, 5)
List.fill(3)("foo") // List(foo, foo, foo)
List.tabulate(3)(n => n * n) // List(0, 1, 4)
List.tabulate(4)(n => n * n) // List(0, 1, 4, 9)
Functional methods on sequences:
// these examples use a List, but they’re the same with Vector
val a = List(10, 20, 30, 40, 10) // List(10, 20, 30, 40, 10)
a.contains(20) // true
a.distinct // List(10, 20, 30, 40)
a.drop(2) // List(30, 40, 10)
a.dropRight(2) // List(10, 20, 30)
a.dropWhile(_ < 25) // List(30, 40, 10)
a.filter(_ < 25) // List(10, 20, 10)
a.filter(_ > 100) // List()
a.find(_ > 20) // Some(30)
a.head // 10
a.headOption // Some(10)
a.init // List(10, 20, 30, 40)
a.last // 10
a.lastOption // Some(10)
a.slice(2,4) // List(30, 40)
a.tail // List(20, 30, 40, 10)
a.take(3) // List(10, 20, 30)
a.takeRight(2) // List(40, 10)
a.takeWhile(_ < 30) // List(10, 20)
// map, flatMap
val fruits = List("apple", "pear")
fruits.map(_.toUpperCase) // List(APPLE, PEAR)
fruits.flatMap(_.toUpperCase) // List(A, P, P, L, E, P, E, A, R)
val nums = List(10, 5, 8, 1, 7)
nums.sorted // List(1, 5, 7, 8, 10)
nums.sortWith(_ < _) // List(1, 5, 7, 8, 10)
nums.sortWith(_ > _) // List(10, 8, 7, 5, 1)
List(1,2,3).updated(0,10) // List(10, 2, 3)
List(2,4).union(List(1,3)) // List(2, 4, 1, 3)
// zip
val women = List("Wilma", "Betty") // List(Wilma, Betty)
val men = List("Fred", "Barney") // List(Fred, Barney)
val couples = women.zip(men) // List((Wilma,Fred), (Betty,Barney))
Scala has many more methods that are available to you. The benefits of all these methods are:
- You don’t have to write custom
for
loops to solve problems - When you read someone else’s code, you won’t have to read their custom
for
loops; you’ll just find common methods like these, so it’s easier to read code from different projects
Tuples
When you want to put multiple data types in the same list, JavaScript lets you do this:
let stuff = ["Joe", 42, 1.0];
In Scala you do this:
val a = ("eleven")
val b = ("eleven", 11)
val c = ("eleven", 11, 11.0)
val d = ("eleven", 11, 11.0, Person("Eleven"))
In Scala these types are called tuples, and as shown, they can contain one or more elements, and the elements can have different types.
You access their elements just like you access elements of a List
, Vector
, or Array
:
d(0) // "eleven"
d(1) // 11
Enumerations
JavaScript doesn’t have enumerations, but you can do this:
let Color = {
RED: 1,
GREEN: 2,
BLUE: 3
};
Object.freeze(Color);
In Scala 3 you can do quite a few things with enumerations. You can create an equivalent of that code:
enum Color:
case Red, Green, Blue
You can create a parameterized enum:
enum Color(val rgb: Int):
case Red extends Color(0xFF0000)
case Green extends Color(0x00FF00)
case Blue extends Color(0x0000FF)
You can also create user-defined enum members:
enum Planet(mass: Double, radius: Double):
case Mercury extends Planet(3.303e+23, 2.4397e6)
case Venus extends Planet(4.869e+24,6.0518e6)
case Earth extends Planet(5.976e+24,6.37814e6)
// more planets here ...
private final val G = 6.67300E-11
def surfaceGravity = G * mass / (radius * radius)
def surfaceWeight(otherMass: Double) = otherMass * surfaceGravity
Scala.js DOM Code
Scala.js lets you write Scala code that is compiled to JavaScript code that can then be used in the browser. The approach is similar to TypeScript, ReScript, and other languages that are compiled to JavaScript.
Once you include the necessary libraries, and import the necessary packages in your project, writing Scala.js code looks very similar to writing JavaScript code:
// show an alert dialog on a button click
jQuery("#hello-button").click{() =>
dom.window.alert("Hello, world")
}
// define a button and what should happen when it’s clicked
val btn = button(
"Click me",
onclick := { () =>
dom.window.alert("Hello, world")
})
// create two divs with css classes, an h2 element, and the button
val content =
div(cls := "foo",
div(cls := "bar",
h2("Hello"),
btn
)
)
// add the content to the DOM
val root = dom.document.getElementById("root")
root.innerHTML = ""
root.appendChild(content.render)
Note that although Scala is a type-safe language, no types are declared in the above code. Scala’s strong type inference capabilities often make Scala code look like it’s dynamically typed. But it is type-safe, so you catch many classes of errors early in the development cycle.
Other Scala.js resources
The Scala.js website has an excellent collection of tutorials for JavaScript developers interested in using Scala.js. Here are some of their initial tutorials:
- Basic tutorial (creating a first Scala.js project)
- Scala.js for JavaScript developers
- From ES6 to Scala: Basics
- From ES6 to Scala: Collections
- From ES6 to Scala: Advanced
Concepts that are unique to Scala
There are other concepts in Scala which currently have no equivalent in JavaScript:
- Almost everything related to contextual abstractions
- Method features:
- Multiple parameter lists
- Using named arguments when calling methods
- Using traits as interfaces
- Case classes
- Companion classes and objects
- The ability to create your own control structures and DSLs
- Advanced features of
match
expressions and pattern matching for
comprehensions- Infix methods
- Macros and metaprogramming
- More …