Operators allow you to get two simple expressions and combine them to form a more complex expression.

We can classify operators based on the operands they work with. An operand is a simple expression. Some operators work with 1 operand. Most with 2 operands. Just one operator works with 3 operands.

The operator that works with 3 operands is the ternary operator, a succint way to express conditionals:

```
<condition> ? <expression> : <expression>
```

The `<condition>`

is evaluated as a boolean, and upon the result, the operator runs the first expression (if the condition is true) or the second.

Example usage:

```
const running = true
(running === true) ? stop() : run()
```

We have the only 3-operands operator out of the way, so we can divide the rest of them in 2 parts: **unary operators**, and **binary operators**. After that, I will introduce the operator precedence concept.

## Unary operators

### Increment (++)

Increment a number. This is a unary operator, and if put before the number, it returns the value incremented.

If put after the number, it returns the original value, then increments it.

```
let x = 0
x++ //0
x //1
++x //2
```

### Decrement (`--`

)

Works like the increment operator, except it decrements the value.

```
let x = 0
x-- //0
x //-1
--x //-2
```

### Unary negation (-)

Return the negation of the operand

```
let x = 2
-x //-2
x //2
```

### Unary plus (+)

If the operand is not a number, it tries to convert it. Otherwise if the operand is already a number, it does nothing.

```
let x = 2
+x //2
x = '2'
+x //2
x = '2a'
+x //NaN
```

### Logical not (!)

Invert the value of a boolean:

```
let value = true
!value //false
```

### new

The new operator is used to create a new object. You follow `new`

with the object class to create a new object of that type:

```
const date = new Date()
```

## delete

`delete`

is an operator which is not using a punctuation character, but is still an operator. It deletes a property from an object.

```
const car = {
model: 'Fiesta',
color: 'green'
}
delete car.model
delete car['color']
```

## typeof

`typeof`

returns a string representing the type of a variable:

```
typeof 'Flavio' //string
typeof 22 //number
```

## await

`await`

can only be used inside async functions, and it’s a way to signal JavaScript to wait for a promise to resolve. Don’t worry, we’ll talk about this extensively later.

```
const result = await something()
```

## Spread operator

You can expand an array, an object or a string using the spread operator `...`

.

Let’s start with an array example. Given

```
const a = [1, 2, 3]
```

you can create a new array using

```
const b = [...a, 4, 5, 6]
```

You can also create a copy of an array using

```
const c = [...a]
```

This works for objects as well. Clone an object with:

```
const newObj = { ...oldObj }
```

Using strings, the spread operator creates an array with each char in the string:

```
const hey = 'hey'
const arrayized = [...hey] // ['h', 'e', 'y']
```

This operator has some pretty useful applications. The most important one is the ability to use an array as function argument in a very simple way:

```
const f = (foo, bar) => {}
const a = [1, 2]
f(...a)
```

The **rest element** is useful when working with **array destructuring**:

```
const numbers = [1, 2, 3, 4, 5]
const [first, second, ...others] = numbers
```

and **spread elements**:

```
const numbers = [1, 2, 3, 4, 5]
const sum = (a, b, c, d, e) => a + b + c + d + e
const sum = sum(...numbers)
```

ES2018 introduces rest properties, which are the same but for objects.

**Rest properties**:

```
const { first, second, ...others } = {
first: 1,
second: 2,
third: 3,
fourth: 4,
fifth: 5
}
first // 1
second // 2
others // { third: 3, fourth: 4, fifth: 5 }
```

**Spread properties** allow to create a new object by combining the properties of the object passed after the spread operator:

```
const items = { first, second, ...others }
items //{ first: 1, second: 2, third: 3, fourth: 4, fifth: 5 }
```

It is also the perfect way to merge two simple objects into one:

```
const object1 = {
name: 'Flavio'
}
const object2 = {
age: 35
}
const object3 = {...object1, ...object2 }
```

## Binary operators

### Addition (+)

```
const three = 1 + 2
const four = three + 1
```

The `+`

operator also serves as string concatenation if you use strings, so pay attention:

```
const three = 1 + 2
three + 1 // 4
'three' + 1 // three1
```

### Subtraction (-)

```
const two = 4 - 2
```

### Division (/)

Returns the quotient of the first operator and the second:

```
const result = 20 / 5 //result === 4
const result = 20 / 7 //result === 2.857142857142857
```

If you divide by zero, JavaScript does not raise any error but returns the `Infinity`

value (or `-Infinity`

if the value is negative).

```
1 / 0 //Infinity
-1 / 0 //-Infinity
```

### Remainder (%)

The remainder is a very useful calculation in many use cases:

```
const result = 20 % 5 //result === 0
const result = 20 % 7 //result === 6
```

A reminder by zero is always `NaN`

, a special value that means “Not a Number”:

```
1 % 0 //NaN
-1 % 0 //NaN
```

### Multiplication (*)

Multiply two numbers

```
1 * 2 //2
-1 * 2 //-2
```

### Exponentiation (**)

Raise the first operand to the power second operand

```
1 ** 2 //1
2 ** 1 //2
2 ** 2 //4
2 ** 8 //256
8 ** 2 //64
```

The exponentiation operator `**`

is the equivalent of using `Math.pow()`

, but brought into the language instead of being a library function.

```
Math.pow(4, 2) == 4 ** 2
```

This feature is a nice addition for math intensive JS applications.

The `**`

operator is standardized across many languages including Python, Ruby, MATLAB, Lua, Perl and many others.

### Assignment

Use `=`

to assign a value to a variable:

```
const a = 2
let b = 2
var c = 2
```

### Comparisons

You can use the following operators to compare two numbers, or two strings. Returns a boolean:

`<`

less than`<=`

minus than, or equal to`>`

greater than`>=`

greater than, or equal to

```
const a = 2
a >= 1 //true
```

When comparing strings, it checks for the letter ordering, encoded in Unicode.

### Equality checks

Accepts two values, and returns a boolean:

`==`

checks for equality`!=`

checks for inequality`===`

checks for strict equality`!==`

checks for strict inequality

Let’s talk what we mean for *strict*. Without the strict check, the second operand is converted to the type of the first before making the comparison. Strict prevents this.

Examples:

```
const a = true
a == true //true
a === true //true
1 == 1 //true
1 == '1' //true
1 === 1 //true
1 === '1' //false
```

You cannot check objects for equality: two objects are never equal to each other. The only case when a check might be true is if two variables reference the same object.

Some peculiarities to be aware: `NaN`

is always different from `NaN`

.

```
NaN == NaN //false
```

`null`

and `undefined`

values are equal if compared in non-strict mode:

```
null == undefined //true
null === undefined //false
```

### Logical and

Returns true if both operands are true:

```
<expression> && <expression>
```

For example:

```
a === true && b > 3
```

The cool thing about this operator is that the second expression is never executed if the first evaluates to false. Which has some practical applications, for example, to check if an object is defined before using it:

```
const car = { color: 'green' }
const color = car && car.color
```

### Logical or

Returns true if at least one of the operands is true:

```
<expression> || <expression>
```

For example:

```
a === true || b > 3
```

This operator is very useful to fallback to a default value. For example:

```
const car = {}
const color = car.color || 'green'
```

makes `color`

default to `green`

if `car.color`

is not defined.

### instanceof

Return true if the first operand is an instance of the object passed on the right, or one of its ancestors in its prototype chain:

```
class Car {}
class Fiesta extends Car {}
const myCar = new Fiesta()
myCar instanceof Fiesta //true
myCar instanceof Car //true
```

### in

Return true if the first operand is a property of the object passed on the right, or a property of one of its ancestors in its prototype chain:

```
class Car {
constructor() {
this.wheels = 4
}
}
class Fiesta extends Car {
constructor() {
super()
this.brand = 'Ford'
}
}
const myCar = new Fiesta()
'brand' in myCar //true
'wheels' in myCar //true
```

### Assignment shortcuts

The regular assignment operator, `=`

, has several shortcuts for all the arithmetic operators which let you combine assignment, assigning to the first operand the result of the operations with the second operand.

They are:

`+=`

: addition assignment`-=`

: subtraction assignment`*=`

: multiplication assignment`/=`

: division assignment`%=`

: remainder assignment`**=`

: exponentiation assignment

Examples:

```
let a = 0
a += 5 //a === 5
a -= 2 //a === 3
a *= 2 //a === 6
a /= 2 //a === 3
a %= 2 //a === 1
```

## Precedence rules

Every complex statement will introduce precedence problems.

Take this:

```
const a = 1 * 2 + 5 / 2 % 2
```

The result is 2.5, but why? What operations are executed first, and which need to wait?

Some operations have more precedence than the others. The precedence rules are listed in this table:

Operator | Description |
---|---|

`-` `+` `++` `--` |
unary operators, increment and decrement |

`*` `/` `%` |
multiply/divide |

`+` `-` |
addition/subtraction |

`=` `+=` `-=` `*=` `/=` `%=` `**=` |
assignments |

Operations on the same level (like `+`

and `-`

) are executed in the order they are found

Following this table, we can solve this calculation:

```
const a = 1 * 2 + 5 / 2 % 2
const a = 2 + 5 / 2 % 2
const a = 2 + 2.5 % 2
const a = 2 + 0.5
const a = 2.5
```

I didn’t talk about bitwise operators, which are a bit too advanced for this course level, and other operators like void or other very rarely used ones.