Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

75%
+4 −0
Q&A What's the difference between =, == and === operators in JavaScript?

Assignment (=) = is the assignment operator: it assigns a value to "something". One important detail is that an assignment expression not only assigns a value, but it also returns it. This allows...

posted 2y ago by hkotsubo‭  ·  edited 2y ago by hkotsubo‭

Answer
#2: Post edited by user avatar hkotsubo‭ · 2021-07-28T13:20:55Z (over 2 years ago)
  • # Assignment (`=`)
  • `=` is the [assignment operator](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-assignment-operators): it assigns a value to "something".
  • One important detail is that an assignment expression not only assigns a value, but it also returns it. This allows chaining, such as:
  • ```javascript
  • x = y = z = 1; // all variables will be assigned the value 1
  • ```
  • According to the [operator precedence rules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#precedence_and_associativity), assignment is right-associative, so the code above is actually equivalent to:
  • ```javascript
  • x = (y = (z = 1));
  • ```
  • As the expression also returns the assigned value, the code above is evaluated as:
  • - `z` is assigned the value `1`
  • - the expression `z = 1` returns the value `1`
  • - `y` is assigned the value returned by `(z = 1)` (which is also `1`)
  • - the expression `(y = (z = 1))` returns the value `1`
  • - `x` is assigned the value returned by `(y = (z = 1))` (which is also `1`)
  • This allows even more complicated things, such as:
  • ```javascript
  • x = (y = (z = 1) + 1) + y;
  • ```
  • In this case, the code executes as follows:
  • - `z` is assigned the value `1`
  • - the expression `z = 1` returns the value `1`
  • - `y` is assigned the value returned by `(z = 1) + 1` (which is `2`)
  • - the expression `(y = (z = 1) + 1)` returns the value `2`
  • - `x` is assigned the value returned by `(y = (z = 1) + 1) + y` (which is `4`)
  • Although I'd never use expressions like this in production code. But the fact that an assignment returns a value can be useful in cases like this:
  • ```javascript
  • while ((x = somefunc()) >= 0) {
  • // do something with x
  • }
  • ```
  • Assuming that `somefunc` returns some number, and I want to loop until this number is negative (and also do something with it inside the loop). Of course I could rewrite the same code as:
  • ```javascript
  • while (true) {
  • x = somefunc();
  • if (x <= 0)
  • break;
  • // do something with x
  • }
  • ```
  • But I think the former is more straighforward.
  • ---
  • Another caveat regards to variable declaration. See this code:
  • ```java
  • const x = y = 1;
  • y = 2; // ok
  • x = 2; // ERROR
  • ```
  • A `const` variable can't be changed through assignment, so trying to assign `x = 2` causes an error. But `y = 2` is perfectly fine, because `const` applies only to `x`. Remember that `=` is right-associative, so the first line above corresponds to:
  • ```javascript
  • const x = (y = 1);
  • ```
  • If I want both `x` and `y` to be constants, I'd have to do this:
  • ```javascript
  • const x = 1, y = 1;
  • ```
  • ---
  • And last but not least, the left side of `=` is not restricted to single variable names:
  • ```javascript
  • // if x is an array, assign value to specific index
  • x[2] = value;
  • // assign value to a property of "x" object
  • x.property = value;
  • // if value is an array, x and y will be its first and second elements
  • [x, y] = value;
  • // destructuring assignment, get "name" and "age" properties of object and assigning them to the respective variables
  • var { name, age } = obj;
  • ```
  • ---
  • # Equality Operators: `==` vs `===`
  • According to MDN, `==` is the [equality operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) and `===` is the [strict equality operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality), but the ECMAScript language specification just calls them ["Equality Operators"](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators). You can call them "loose" and "strict" equality, though, as these terms usage has become common and well known.
  • Both always return a boolean value (either `true` or `false`). The only difference, according to the [evaluation rules](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators-runtime-semantics-evaluation), is the algorithm used to determine equality.
  • ### `==` or "loose equality"
  • The `==` operator uses the [`IsLooselyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal), which makes some type coercions when the operands are of different types. The rules are somewhat complicated (if you compare a number and a string, the string will be converted to a number using the [rules defined in the spec](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tonumber), but comparing a number and an object will make the object to be [converted to a primitive](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toprimitive), etc).
  • This can cause some strange and unexpected behaviour in many cases, such as `0 == []`, `"1" == [1]` and `"" == [[[]]]`, all of them resulting in `true`.
  • Although chaining this operator produces valid code (aka "it runs without compile-errors"), it doesn't work the way you'd expect. Example:
  • ```javascript
  • x = y = z = 0; // assign zero to all variables
  • console.log(x == y == z); // false
  • ```
  • According to [this table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table), both `==` and `===` are evaluated left-to-right, which means that the expression `x == y == z` is equivalent to:
  • ```javascript
  • (x == y) == z
  • ```
  • Hence, `x == y` evaluates to `true` (as both `x` and `y` are zero), and then `true == z` evaluates to `false`. To test if the three variables are equal, you should do `x == y && y == z` (or `x === y && y === z`).
  • But all these type coercion mess applies only when the two operands are of different types. When they are of the same type, both `==` and `===` behave the same way. In the [specification of `IsLooselyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal), the first step is:
  • 1. If `Type(x)` is the same as `Type(y)`, then
  • - Return `IsStrictlyEqual(x, y)`.
  • And [according to the spec](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators-runtime-semantics-evaluation), the `IsStrictlyEqual` operation is the same one used by the `===` operator.
  • ### `===` or "strict equality"
  • As mentioned above, the `===` operator uses the [`IsStrictlyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-isstrictlyequal), which in turn does the following:
  • - if the operands are of type `Number` or `BigInt`, it calls the respective `equal` operation ([this one](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-equal) for `Number` or [this one](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-bigint-equal) for `BigInt`).
  • - in any other case, it uses the [`SameValueNonNumeric` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevaluenonnumeric), which defines specific rules for each type
  • The difference from `==` is that `===` doesn't do any type coercion: if the operands are of different types, it returns `false` (that's the first thing it checks, BTW).
  • But there's one caveat: the "same type" definition is a little bit tricky when objects are involved. Ex:
  • ```javascript
  • x = [1, 2];
  • y = [1, 2];
  • z = x;
  • console.log(typeof x, typeof y, typeof z); // "object" "object" "object"
  • console.log(x === y); // false (although they have the same type)
  • console.log(x === z); // true (they reference the same object)
  • ```
  • The assignment to `y` actually creates another array (hence, it's a different object, although it has the same values of `x`). And when the operands type is neither `Number`, `BigInt`, `Undefined`, `Null`, `String`, `Boolean` nor `Symbol`, the `SameValueNonNumeric` operation only returns `true` if both operands are the same object.
  • ---
  • The differences between `==` and `===`, and their somewhat complicated rules, might lead to lots of corner cases, such as `null == undefined` being `true` while `null === undefined` is `false`, and many more (some already mentioned in the other answers).
  • [Here](https://dorey.github.io/JavaScript-Equality-Table/) you can find some interesting tables with lots of those cases. I'm reproducing some below.
  • For the `==` operator:
  • ![loose equality](https://software.codidact.com/uploads/pfvqRUNC8DavwLcxmZVNP8Jg)
  • And for the `===` operator:
  • ![strict equality](https://software.codidact.com/uploads/rmwfZwNDjWmwC7cffTMUWVaL)
  • # Assignment (`=`)
  • `=` is the [assignment operator](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-assignment-operators): it assigns a value to "something".
  • One important detail is that an assignment expression not only assigns a value, but it also returns it. This allows chaining, such as:
  • ```javascript
  • x = y = z = 1; // all variables will be assigned the value 1
  • ```
  • According to the [operator precedence rules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#precedence_and_associativity), assignment is right-associative, so the code above is actually equivalent to:
  • ```javascript
  • x = (y = (z = 1));
  • ```
  • As the expression also returns the assigned value, the code above is evaluated as:
  • - `z` is assigned the value `1`
  • - the expression `z = 1` returns the value `1`
  • - `y` is assigned the value returned by `(z = 1)` (which is also `1`)
  • - the expression `(y = (z = 1))` returns the value `1`
  • - `x` is assigned the value returned by `(y = (z = 1))` (which is also `1`)
  • This allows even more complicated things, such as:
  • ```javascript
  • x = (y = (z = 1) + 1) + y;
  • ```
  • In this case, the code executes as follows:
  • - `z` is assigned the value `1`
  • - the expression `z = 1` returns the value `1`
  • - `y` is assigned the value returned by `(z = 1) + 1` (which is `2`)
  • - the expression `(y = (z = 1) + 1)` returns the value `2`
  • - `x` is assigned the value returned by `(y = (z = 1) + 1) + y` (which is `4`)
  • Although I'd never use expressions like this in production code. But the fact that an assignment returns a value can be useful in cases like this:
  • ```javascript
  • while ((x = somefunc()) >= 0) {
  • // do something with x
  • }
  • ```
  • Assuming that `somefunc` returns some number, and I want to loop until this number is negative (and also do something with it inside the loop). Of course I could rewrite the same code as:
  • ```javascript
  • while (true) {
  • x = somefunc();
  • if (x < 0)
  • break;
  • // do something with x
  • }
  • ```
  • But I think the former is more straighforward.
  • ---
  • Another caveat regards to variable declaration. See this code:
  • ```java
  • const x = y = 1;
  • y = 2; // ok
  • x = 2; // ERROR
  • ```
  • A `const` variable can't be changed through assignment, so trying to assign `x = 2` causes an error. But `y = 2` is perfectly fine, because `const` applies only to `x`. Remember that `=` is right-associative, so the first line above corresponds to:
  • ```javascript
  • const x = (y = 1);
  • ```
  • If I want both `x` and `y` to be constants, I'd have to do this:
  • ```javascript
  • const x = 1, y = 1;
  • ```
  • ---
  • And last but not least, the left side of `=` is not restricted to single variable names:
  • ```javascript
  • // if x is an array, assign value to specific index
  • x[2] = value;
  • // assign value to a property of "x" object
  • x.property = value;
  • // if value is an array, x and y will be its first and second elements
  • [x, y] = value;
  • // destructuring assignment, get "name" and "age" properties of object and assigning them to the respective variables
  • var { name, age } = obj;
  • ```
  • ---
  • # Equality Operators: `==` vs `===`
  • According to MDN, `==` is the [equality operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) and `===` is the [strict equality operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality), but the ECMAScript language specification just calls them ["Equality Operators"](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators). You can call them "loose" and "strict" equality, though, as these terms usage has become common and well known.
  • Both always return a boolean value (either `true` or `false`). The only difference, according to the [evaluation rules](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators-runtime-semantics-evaluation), is the algorithm used to determine equality.
  • ### `==` or "loose equality"
  • The `==` operator uses the [`IsLooselyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal), which makes some type coercions when the operands are of different types. The rules are somewhat complicated (if you compare a number and a string, the string will be converted to a number using the [rules defined in the spec](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tonumber), but comparing a number and an object will make the object to be [converted to a primitive](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toprimitive), etc).
  • This can cause some strange and unexpected behaviour in many cases, such as `0 == []`, `"1" == [1]` and `"" == [[[]]]`, all of them resulting in `true`.
  • Although chaining this operator produces valid code (aka "it runs without compile-errors"), it doesn't work the way you'd expect. Example:
  • ```javascript
  • x = y = z = 0; // assign zero to all variables
  • console.log(x == y == z); // false
  • ```
  • According to [this table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table), both `==` and `===` are evaluated left-to-right, which means that the expression `x == y == z` is equivalent to:
  • ```javascript
  • (x == y) == z
  • ```
  • Hence, `x == y` evaluates to `true` (as both `x` and `y` are zero), and then `true == z` evaluates to `false`. To test if the three variables are equal, you should do `x == y && y == z` (or `x === y && y === z`).
  • But all these type coercion mess applies only when the two operands are of different types. When they are of the same type, both `==` and `===` behave the same way. In the [specification of `IsLooselyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal), the first step is:
  • 1. If `Type(x)` is the same as `Type(y)`, then
  • - Return `IsStrictlyEqual(x, y)`.
  • And [according to the spec](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators-runtime-semantics-evaluation), the `IsStrictlyEqual` operation is the same one used by the `===` operator.
  • ### `===` or "strict equality"
  • As mentioned above, the `===` operator uses the [`IsStrictlyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-isstrictlyequal), which in turn does the following:
  • - if the operands are of type `Number` or `BigInt`, it calls the respective `equal` operation ([this one](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-equal) for `Number` or [this one](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-bigint-equal) for `BigInt`).
  • - in any other case, it uses the [`SameValueNonNumeric` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevaluenonnumeric), which defines specific rules for each type
  • The difference from `==` is that `===` doesn't do any type coercion: if the operands are of different types, it returns `false` (that's the first thing it checks, BTW).
  • But there's one caveat: the "same type" definition is a little bit tricky when objects are involved. Ex:
  • ```javascript
  • x = [1, 2];
  • y = [1, 2];
  • z = x;
  • console.log(typeof x, typeof y, typeof z); // "object" "object" "object"
  • console.log(x === y); // false (although they have the same type)
  • console.log(x === z); // true (they reference the same object)
  • ```
  • The assignment to `y` actually creates another array (hence, it's a different object, although it has the same values of `x`). And when the operands type is neither `Number`, `BigInt`, `Undefined`, `Null`, `String`, `Boolean` nor `Symbol`, the `SameValueNonNumeric` operation only returns `true` if both operands are the same object.
  • ---
  • The differences between `==` and `===`, and their somewhat complicated rules, might lead to lots of corner cases, such as `null == undefined` being `true` while `null === undefined` is `false`, and many more (some already mentioned in the other answers).
  • [Here](https://dorey.github.io/JavaScript-Equality-Table/) you can find some interesting tables with lots of those cases. I'm reproducing some below.
  • For the `==` operator:
  • ![loose equality](https://software.codidact.com/uploads/pfvqRUNC8DavwLcxmZVNP8Jg)
  • And for the `===` operator:
  • ![strict equality](https://software.codidact.com/uploads/rmwfZwNDjWmwC7cffTMUWVaL)
#1: Initial revision by user avatar hkotsubo‭ · 2021-07-28T13:19:17Z (over 2 years ago)
# Assignment (`=`)

`=` is the [assignment operator](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-assignment-operators): it assigns a value to "something".

One important detail is that an assignment expression not only assigns a value, but it also returns it. This allows chaining, such as:

```javascript
x = y = z = 1; // all variables will be assigned the value 1
```

According to the [operator precedence rules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#precedence_and_associativity), assignment is right-associative, so the code above is actually equivalent to:


```javascript
x = (y = (z = 1));
```

As the expression also returns the assigned value, the code above is evaluated as:

- `z` is assigned the value `1`
- the expression `z = 1` returns the value `1`
- `y` is assigned the value returned by `(z = 1)` (which is also `1`)
- the expression `(y = (z = 1))` returns the value `1`
- `x` is assigned the value returned by `(y = (z = 1))` (which is also `1`)

This allows even more complicated things, such as:

```javascript
x = (y = (z = 1) + 1) + y;
```

In this case, the code executes as follows:

- `z` is assigned the value `1`
- the expression `z = 1` returns the value `1`
- `y` is assigned the value returned by `(z = 1) + 1` (which is `2`)
- the expression `(y = (z = 1) + 1)` returns the value `2`
- `x` is assigned the value returned by `(y = (z = 1) + 1) + y` (which is `4`)

Although I'd never use expressions like this in production code. But the fact that an assignment returns a value can be useful in cases like this:

```javascript
while ((x = somefunc()) >= 0) {
    // do something with x
}
```

Assuming that `somefunc` returns some number, and I want to loop until this number is negative (and also do something with it inside the loop). Of course I could rewrite the same code as:

```javascript
while (true) {
    x = somefunc();
    if (x <= 0)
        break;
    // do something with x
}
```

But I think the former is more straighforward.

---
Another caveat regards to variable declaration. See this code:

```java
const x = y = 1;
y = 2; // ok
x = 2; // ERROR
```

A `const` variable can't be changed through assignment, so trying to assign `x = 2` causes an error. But `y = 2` is perfectly fine, because `const` applies only to `x`. Remember that `=` is right-associative, so the first line above corresponds to:

```javascript
const x = (y = 1);
```

If I want both `x` and `y` to be constants, I'd have to do this:

```javascript
const x = 1, y = 1;
```

---

And last but not least, the left side of `=` is not restricted to single variable names:

```javascript
// if x is an array, assign value to specific index
x[2] = value;

// assign value to a property of "x" object
x.property = value;

// if value is an array, x and y will be its first and second elements
[x, y] = value;

// destructuring assignment, get "name" and "age" properties of object and assigning them to the respective variables
var { name, age } = obj;
```

---
# Equality Operators: `==` vs `===`

According to MDN, `==` is the [equality operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) and `===` is the [strict equality operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality), but the ECMAScript language specification just calls them ["Equality Operators"](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators). You can call them "loose" and "strict" equality, though, as these terms usage has become common and well known.

Both always return a boolean value (either `true` or `false`). The only difference, according to the [evaluation rules](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators-runtime-semantics-evaluation), is the algorithm used to determine equality.

### `==` or "loose equality"

The `==` operator uses the [`IsLooselyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal), which makes some type coercions when the operands are of different types. The rules are somewhat complicated (if you compare a number and a string, the string will be converted to a number using the [rules defined in the spec](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-tonumber), but comparing a number and an object will make the object to be [converted to a primitive](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toprimitive), etc).

This can cause some strange and unexpected behaviour in many cases, such as `0 == []`, `"1" == [1]` and `"" == [[[]]]`, all of them resulting in `true`.

Although chaining this operator produces valid code (aka "it runs without compile-errors"), it doesn't work the way you'd expect. Example:

```javascript
x = y = z = 0; // assign zero to all variables
console.log(x == y == z); // false
```

According to [this table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table), both `==` and `===` are evaluated left-to-right, which means that the expression `x == y == z` is equivalent to:

```javascript
(x == y) == z
```

Hence, `x == y` evaluates to `true` (as both `x` and `y` are zero), and then `true == z` evaluates to `false`. To test if the three variables are equal, you should do `x == y && y == z` (or `x === y && y === z`).

But all these type coercion mess applies only when the two operands are of different types. When they are of the same type, both `==` and `===` behave the same way. In the [specification of `IsLooselyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal), the first step is:

1. If `Type(x)` is the same as `Type(y)`, then
    - Return `IsStrictlyEqual(x, y)`.

And [according to the spec](https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-equality-operators-runtime-semantics-evaluation), the `IsStrictlyEqual` operation is the same one used by the `===` operator.

### `===` or "strict equality"

As mentioned above, the `===` operator uses the [`IsStrictlyEqual` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-isstrictlyequal), which in turn does the following:

- if the operands are of type `Number` or `BigInt`, it calls the respective `equal` operation ([this one](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-equal) for `Number` or [this one](https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-bigint-equal) for `BigInt`).
- in any other case, it uses the [`SameValueNonNumeric` operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevaluenonnumeric), which defines specific rules for each type

The difference from `==` is that `===` doesn't do any type coercion: if the operands are of different types, it returns `false` (that's the first thing it checks, BTW).

But there's one caveat: the "same type" definition is a little bit tricky when objects are involved. Ex:

```javascript
x = [1, 2];
y = [1, 2];
z = x;
console.log(typeof x, typeof y, typeof z); // "object" "object" "object"
console.log(x === y); // false (although they have the same type)
console.log(x === z); // true (they reference the same object)
```

The assignment to `y` actually creates another array (hence, it's a different object, although it has the same values of `x`). And when the operands type is neither `Number`, `BigInt`, `Undefined`, `Null`, `String`, `Boolean` nor `Symbol`, the `SameValueNonNumeric` operation only returns `true` if both operands are the same object.

---

The differences between `==` and `===`, and their somewhat complicated rules, might lead to lots of corner cases, such as `null == undefined` being `true` while `null === undefined` is `false`, and many more (some already mentioned in the other answers).

[Here](https://dorey.github.io/JavaScript-Equality-Table/) you can find some interesting tables with lots of those cases. I'm reproducing some below.

For the `==` operator:

![loose equality](https://software.codidact.com/uploads/pfvqRUNC8DavwLcxmZVNP8Jg)

And for the `===` operator:

![strict equality](https://software.codidact.com/uploads/rmwfZwNDjWmwC7cffTMUWVaL)