Reason and JavaScript are not the same languages, although the syntax looks similar.
That’s intentional, but sometimes hides fundamental differences of those languages.

Comparing values is a common task in programming. Let’s look at the equality operators.

Checking For Equality in JavaScript

Here’s what MDN has to say:

Equality (==)

The equality operator converts the operands if they are not of the same type, then applies strict comparison. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

Identity / strict equality (===)

The identity operator returns true if the operands are strictly equal (see above) with no type conversion.

JavaScript is a weakly dynamically typed language.
What does that mean?

Every language has types for its values. For example, a value can be an integer, or a floating point number.
Some languages will coerce types automatically. Meaning, if you add the number 2 to 4.4, the language will convert those types; then sum them.
JavaScript is such a language.

2 + 4.4
// 6.4
# `2` is an integer, `4.4` is a floating point number
# JS turned `2` to a float, then added `2` and `4.4` with the addition operator

Thus, there are two kinds of equality operators in JavaScript. The “normal” operator (==) first coerces the types, and then does a comparison between values. For example, compare the number 5 to the string "5".

5 == '5'
// true

The strict comparison operator doesn’t coerce types:

5 === '5'
// false

Does JavaScript compare by value or by reference?

JavaScript stores variables by value for primitive values (things like String or Number).

var a = 5
# stores a value (the "whole thing")

If you want to copy a, you’ll copy the “content” of a.

var b = a
# now `a` and `b` both hold the value 5

But objects and arrays are stored by reference. The variable is a placeholder that points to the actual data.

var objectA = {
  a: 5
}
# `objectA` points to a the data, but it doesn't store the data itself

We can copy objectA:

var objectB = objectA
# now the both point to the same data

If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

objectA == objectB
// true
# both variables point to the same data
objectA === objectB
// true
# both variables point to the same data

Checking For Equality in Reason

Reason also has two equality operators: == for structural comparison, and === for comparison by reference.

So, is this the same as in JavaScript?

Not really.

Reason is strongly typed. We don’t have to concern ourselves with type coercion.
For example, you can’t add a floating point number to an integer. Those are different types, and the + operator doesn’t allow you to work with two different types.

So, why do we have two comparison operators if we don’t have to deal with type coercion?

What does structural equality vs. physical equality mean?

You can check out the documentation for a definition.
But I found the explanation from the blog post by “The Always Learning Marty” most helpful:

Structural qualities concern the current contents of the arguments only. Structural comparisons are therefore more straight forward: compare the contents of the arguments.

Physical qualities concern the physical property. Two things are physically equal if and only if changing one changes the other. The distinction between structural and physical comparisons is especially important for mutable data types.

Reason is immutable by default. Thus, the “normal” equality operator should suffice for most cases.

But there are ways to use mutable values, for example, a Ref.

let foo = ref(5);
> val foo: int ref = {contents = 5}
# foo is defined with a changeable value of 5

let bar = foo
> val bar: int ref = {contents = 5}
# now `bar` is the same (physically) as `foo`

# what happens if we change the ref?
foo := 6;
> : unit = ()
foo;
> : int ref = {content = 6 }

# does `bar` change, too?
bar;
> : int ref = {content = 6 }

foo == bar;
> : bool = true
# they are structurally the same

foo === bar;
# they are physically the same

It’s Not the Same

You’ve now seen some different underlying principles of JavaScript and Reason.
That applies to the equality operators, too.

I haven’t talked about comparing other structures like sets or hashmaps. This post was about the equality operators.

Let’s not forget that the similar syntax can hide diverging models.
Things are not the same (but they might be equal 😉).

Further Reading