-
Notifications
You must be signed in to change notification settings - Fork 9
Operators
Operators are constructs which behave generally like functions, but which differ syntactically or semantically from usual functions.
x OP
x++
x--
delete xOP x
++x - x + '3' // 3 (number)
!xx OP y
x || y
x && y
12 % 5 // 2condition ? x : y
let status = age >= 18 ? 'adult' : 'minor'let status = age >= 18 ? 'adult' : 'minor'condition ? expression : expression
The conditional (ternary) operator is the only JavaScript operator that takes three operands. This operator is frequently used as a shortcut for the
ifstatement.
As an expression:
'The fee is ' + (isMember ? '$2.00' : '$10.00')To declare a variable:
let fee = isMember ? '$2.00' : '$10.00'To create a property:
{
fee: isMember ? '$2.00' : '$10.00'
}let check1 = false,
check2 = false,
access
access = check1 ? 'Denied' : check2 ? 'Denied' : 'Granted'
console.log(access) // "Access granted"let stop = false,
age = 23
age > 18
? (alert('OK, you can go.'), location.assign('continue.html'))
: ((stop = true), alert('Sorry, you are much too young!'))Arithmetic operators take numerical values (either literals or variables) as their operands and return a single numerical value.
+x
The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already.
;+3 + // 3
'3' + // 3
'a' + // NaN
true + // 1
false + // 0
null // 0Note: NaN is a property of the global object. MDN // NaN
-x
The unary negation operator precedes its operand and negates it.
;-'4' - 'a' // -4 // NaN
x = 4
y = -x // y = -4, x = 4x + y
The addition operator produces the sum of numeric operands or string concatenation.
// Number + Number
1 + 2 // 1 + 2 = 3
// Boolean + Number
true + 1 // 1 + 1 = 2
// Boolean + Boolean
true + false + true + true // 1 + 0 + 1 + 1 = 3// Number + String
5 + 'foo'
// "5" + "foo" = "5foo"
// String + Boolean
'foo' + false
// "foo" + "false" = "foofalse"
// String + String
'foo' + 'bar'
// "foo" + "bar" = "foobar"Addition operators are parsed from left to right
// Number + String + Number
5 + 'foo' + 5
// ("5" + "foo") + 5 = "5foo5"
// Number + Number + String
5 + 5 + 'foo'
// (5 + 5) + "foo" = "10foo"
// Number + Number + Boolean + String
5 + 5 + true + 'foo'
// ((5 + 5) + true) + "foo" = "11foo"x - y
The subtraction operator subtracts the two operands, producing their difference.
5 - 3 // 2
3 - 5 // -2
'foo' - 3 // NaNx / y
The division operator produces the quotient of its operands where the left operand is the dividend and the right operand is the divisor.
1 / 2 // 0.5
1.0 / 2.0 // 0.5
2.0 / 0 // InfinityNote: The global Infinity property is a numeric value representing infinity. MDN | Infinity
x * y
The multiplication operator produces the product of the operands.
2 * 2 // 4
'2' * 2 - // 4
2 * 2 // -4
'-2' * 2 // -4
'foo' * 2 // NaN
Infinity * 0 // NaN
Infinity * Infinity // InfinityThe multiplication operator has higher precedence than the addition operator.
// Number + Number + Number
3 + 4 + 5
// (3 + 4) + 5 = 12
// Number + Number * Number
3 + 4 * 5
// 3 + (4 * 5) = 23
// Number + Number * Number
3 + '4' * 5
// 3 + ("4" * 5) = 23x % y
Returns the remainder left over when one operand is divided by a second operand.
12 % 5 // 2
2 % 3 - // 2
1 % 2 // -1x ** y
The exponentiation operator returns the result of raising first operand to the power second operand.
2 ** 3 // 2 * 2 * 2 = 8
3 ** 2 // 3 * 3 = 9x++ or ++x
The increment operator increments (adds one to) its operand and returns a value.
// Postfix
let x = 3
y = x++
// x = 4, y = 3// Prefix
let x = 2
y = ++x
// x = 3, y = 3x-- or --x
The decrement operator decrements (subtracts one from) its operand and returns a value.
// Postfix
let x = 3
y = x--
// x = 2, y = 3// Prefix
let x = 2
y = --x
// x = 1, y = 1The basic assignment operator is equal (=), which assigns the value of its right operand to its left operand.
x = y
Simple assignment operator which assigns a value to a variable.
let x = 5,
y = 10,
z = 25
x = y // x is 10
x = y = z // x, y and z are all 25
console.log((x = 3 + 2)) // 5
console.log((x = y = z)) // 25| Name | Operator | Meaning |
|---|---|---|
| Addition assignment | x += y |
x = x + y |
| Subtraction assignment | x -= y |
x = x - y |
| Multiplication assignment | x *= y |
x = x * y |
| Division assignment | x /= y |
x = x / y |
| Remainder assignment | x %= y |
x = x % y |
| Exponentiation assignment | x **= y |
x = x ** y |
The destructuring assignment syntax is a JavaScript expression that makes it possible to extract data from arrays or objects into distinct variables.
MDN // Destructuring assignment
With arrays, destructuring is made by order
With destructuring:
const numbers = ['one', 'two', 'three']
const [one, two, three] = numbers
console.log(one, two, three) // "one", "two", "three"Without destructuring:
const numbers = ['one', 'two', 'three']
const one = numbers[0]
const two = numbers[1]
const three = numbers[2]
console.log(one, two, three) // "one", "two", "three"Destructuring declares new variables, and follows the same rules as any variable declaration.
let x = [1, 2, 3, 4, 5]let [y, z] = x
// let y = x[0]
// let z = x[1]const [y, z] = x
// const y = x[0]
// const z = x[1]Note: as we are declaring new variables y and z and asigning a value,
we need to use var, otherwise variables will be declared on global scope.
A variable can be assigned its value via destructuring separate from the variable's declaration.
without destructuring:
let x = 1
let y = 2
let z = 3with destructuring:
let [x, y, z] = [1, 2, 3]A variable can be assigned a default, in the case that the value pulled from the array is undefined.
let arr = [1, undefined, 3, null, '']without destructuring:
let a = chars[0] !== undefined ? chars[0] : 'a'
let b = chars[1] !== undefined ? chars[1] : 'b'
let c = chars[2] !== undefined ? chars[2] : 'c'
let d = chars[3] !== undefined ? chars[3] : 'd'
let e = chars[4] !== undefined ? chars[4] : 'e'
console.log(a, b, c, d, e) // 1, "b", 3, null, ""with destructuring:
let [a = 'a', b = 'b', c = 'c', d = 'd', e = 'e'] = arr
console.log(a, b, c, d, e) // 1, "b", 3, null, ""Note: Notice that default values only works with undefined values, not with null or falsey values.
Two variables values can be swapped in one destructuring expression.
let a = 1
let b = 3
;[a, b] = [b, a]
console.log(a, b) // 3, 1You can ignore return values that you're not interested in
let numbers = [1, 2, 3, 4, 5, 6]without destructuring:
let a = numbers[0]
let b = numbers[2]
let c = numbers[5]
console.log(a, b, c) // 1, 3, 6with destructuring:
let [a, , b, , , c] = numbers
console.log(a, b, c) // 1, 3, 6let arrays = [[1, 2, 3], [4, 5, 6]]
let [[a, , b], [c, d]] = arrays
console.log(a, b, c, d) // 1, 3, 4, 5With objects, destructuring is made by property name, not by order
let o = { a: 42, b: true, c: 36, d: 'Evan' }with destructuring:
let { a, d } = o
console.log(a, d) // 42, 'Evan'without destructuring:
let a = o.a
let d = o.d
console.log(a, d) // 42, 'Evan'with destructuring:
let { a = 10, b = 5 } = { a: 3 }
console.log(a, b) // 3, 5without destructuring:
let _ref = { a: 3 }
let a = _ref.a !== undefined ? _ref.a : 10
let b = _ref.b !== undefined ? _ref.b : 5
console.log(a, b) // 3, 5let o = { a: 42, b: true, c: 36, d: 'Evan' }with destructuring:
let { a: first, d: second } = o
console.log(first, second) // 42, 'Evan'without destructuring:
let first = o.a
let second = o.d
console.log(first, second) // 42, 'Evan'let o = { a: 42, b: true, c: 36, d: 'Evan' }with destructuring:
let { a: first, c = 10, d: second, e: third = 6 } = o
console.log(first, second, third) // 42, 'Evan', 6without destructuring:
let first = o.a
let c = o.c !== undefined ? o.c : 10
let second = o.d
let third = o.e !== undefined ? o.e : 6
console.log(first, second, third) // 42, 'Evan', 6without destructuring:
// `options` is an object
let size = options.size === undefined ? 'big' : options.size
let cords = options.cords === undefined ? { x: 0, y: 0 } : options.cords
let radius = options.radius === undefined ? 25 : options.radius
console.log(size, cords, radius)with destructuring:
// `options`is an object
let { size = 'big', cords = { x: 0, y: 0 }, radius = 25 } = optionsdrawChart({ radius: 45 })with destructuring:
function drawChart({ size = 'big', cords = { x: 0, y: 0 }, radius = 25 } = {}) {
console.log(size, cords, radius)
}without destructuring:
function drawChart(options) {
options = options === undefined ? {} : options
let size = options.size === undefined ? 'big' : options.size
let cords = options.cords === undefined ? { x: 0, y: 0 } : options.cords
let radius = options.radius === undefined ? 25 : options.radius
console.log(size, cords, radius)
}let users = [{ name: 'Evan' }, { name: 'Joseph' }]
let [{ name: name1 }, { name: name2 }] = users
console.log(name1) // "Evan"
console.log(name2) // "Joseph"const metadata = {
title: 'Scratchpad',
translations: [
{
url: '/de/docs/Tools/Scratchpad',
title: 'JavaScript-Umgebung'
}
],
url: '/en-US/docs/Tools/Scratchpad'
}
let { title: englishTitle, translations: [{ title: localeTitle }] } = metadata
console.log(englishTitle) // "Scratchpad"
console.log(localeTitle) // "JavaScript-Umgebung"x OP y
JavaScript has both strict and type–converting comparisons.
x == y
x != y
Converts the operands to the same type before making the comparison.
x == y
1 == 1 // true
'1' == 1 // true
1 == '1' // true
0 == false // true
0 == null // false
0 == undefined // false
null == undefined // trueTwo distinct objects are never equal for either strict or abstract comparisons.
An expression comparing objects is only true if the operands reference the same object.
const object1 = { value: 'key' }
const object2 = { value: 'key' }
object1 == object2 // false
const object3 = object1
object1 == object3 // trueNote: The two objects are difference objects, in different allocation. They are not the same object.
x != y
1 != 2 // true
1 != '1' // false
1 != '1' // false
1 != true // false
0 != false // falseThe string is converted to a number value.
'1' == 1 // true
// 1 == 1 // trueThe Boolean operand is converted to 1 if it is true and 0 if it is false.
0 == false // true
// 0 == 1 // true
1 == true // true
// 1 == 1 // true
1 == false // false
// 1 == 0 // falseJavaScript attempts to return the default value for the object.
let a = new String('foo')
let b = new String('foo')
a == b // false, as a and b are both objects and reference different objects
// a = b // false
a == 'foo' // true, as the Object (a) is converted to String 'foo'
// 'foo' = 'foo' // trueEach of these operators will call the
valueOf()function on each operand before a comparison is made.Then, the primitive values are compared
MDN // Object.protrotype.valueOf()
let a = new Number(5)
let b = new Number(5)
a == b // false as a and b are type Object and reference different objects
a == 5 // true as the Object (a) is converted to primitive 5 before comparison
a > b // false
a < b // falseEnforcing valueOf():
let o = {
valueOf: function() {
return 'random'
}
}
o == 'random' // truex === y
x !== y
A strict comparison is only true if the operands are of the same type and the contents match.
1 === 1 // true (true in abstract comparison)
'1' === 1 // false (true in abstract comparison)
1 === '1' // false (true in abstract comparison)
0 === false // false (true in abstract comparison)
0 === null // false (false in abstract comparison)
0 === undefined // false (false in abstract comparison)
null === undefined // false (true in abstract comparison)x != y
1 !== 2 // true
1 !== '1' // true (false in abstract comparison)
1 !== '1' // true (false in abstract comparison)
1 !== true // true (false in abstract comparison)
0 !== false // true (false in abstract comparison)x > y
x >= y
x < y
x <= y
4 > 3 // true
4 >= 3 // true
3 >= 3 // true
3 < 4 // true
3 <= 4 // true
3 <= 3 // trueexpression && expression
expression || expression
!expression
Logical operators are typically used with
Boolean(logical) valuesHowever, the
&&and||operators actually return the value of one of the specified operands, so if these operators are used with non-Boolean values, they may return a non-Boolean value.
expression && expression
The return is not
trueorfalse, it's the last evaluated expression
true && true // t && t returns true
true && false // t && f returns false
false && true // f && t returns false
false && 3 == 4 // f && f returns false
'Cat' && 'Dog' // t && t returns Dog
false && 'Cat' // f && t returns false
'Cat' && false // t && f returns falseexpression || expression
The return is not
trueorfalse, it's the last evaluated expression
true || true // t || t returns true
false || true // f || t returns true
true || false // t || f returns true
false || 3 == 4 // f || f returns false
'Cat' || 'Dog' // t || t returns Cat
false || 'Cat' // f || t returns Cat
'Cat' || false // t || f returns CatWith non-Boolean values, "falsey" expressions are evaluated to false:
undefined,null,NaN,0,""
let a
a || 'truthy' // "truthy"
null || 'truthy' // "truthy"
NaN || 'truthy' // "truthy"
0 || 'truthy' // "truthy"
'' || 'truthy' // "truthy"Note: The return is not true or false, it's the last evaluated expression.
!expression
!true // !t returns false
!false // !f returns true
!'Cat' // !t returns falseAs logical expressions are evaluated left to right, they are tested for possible "short-circuit" evaluation.
3 && '' && 'Cat' // false | 3 and "" are evaluated
// "Cat" isn't evaluated as "" was falsey3 || '' || 'Cat' // true | 3 is evaluated
// "" and "Cat" aren't evaluated as 3 was thruthyThis code:
let flag = doSomething()
if (!flag) {
doSomethingElse()
}is the same as:
doSomething() || doSomethingElse()This code:
let flag = doSomething()
if (flag) {
doSomethingElse()
}is the same as:
doSomething() && doSomethingElse()OP x
An unary operation is an operation with only one operand.
delete x
The
deleteoperator deletes an object, an object's property, or an element at a specified index in an array.
obj = { name: 'Joseph', surname: 'Smith' }
delete obj.name // obj === { surname: 'Smith' }
delete obj // obj is not defined
arr = [1, 2, 3, 4]
delete arr[1] // arr === [1,undefined, 3,4]
delete arr // arr is not definedObjects (and arrays) can be deleted only if they are declared implicitly
let obj = { name: 'Joseph', surname: 'Smith' }
delete obj // obj is { name: 'Joseph', surname: 'Smith' }
let arr = [1, 2, 3, 4]
delete arr // arr is [1,2,3,4]typeof x
The
typeofoperator returns a string indicating the type of the unevaluated operand.
typeof x // "undefined"
typeof 5 // "number"
typeof '5' // "string"
typeof {} // "object"
typeof null // "object"| Type | Result |
|---|---|
| Undefined | "undefined" |
| Boolean | "boolean" |
| Number | "number" |
| String | "string" |
| Symbol (ES6) | "symbol" |
| Function object | "function" |
| Any other object | "object" |
...x
The spread syntax allows an expression to be expanded in places where comma separated variables are expected.
numbers passed as a single argument to console.log:
let numbers = [1, 2, 3]
console.log(numbers)
// [1, 2, 3]numbers spread, as separated arguments:
let numbers = [1, 2, 3]
console.log(...numbers)
// 1, 2, 3which is the same as:
// console.log(...numbers)
console.log(numbers[0], numbers[1], numbers[2])let numbers = [1, 2, 3]
let letters = ['a', 'b', 'c']
[...numbers, ...letters]
// [1, 2, 3, 'a', 'b', 'c']let parts = ['shoulders', 'knees']
let lyrics = ['head', ...parts, 'and', 'toes']
console.log(lyrics)
// ["head", "shoulders", "knees", "and", "toes"]let arr = [1, 2, 3]
let arr2 = [...arr] // [arr[0],arr[1],arr[2]]
arr2.push(4) // [1, 2, 3, 4]arr2 becomes [1,2,3,4], arr stays the same
let user = { name: 'Evan', surname: 'Graham' }
let userWithJob = { ...user, job: 'Barber' }
console.log(user) // {name: "Evan", surname: "Graham"}
console.log(userWithJob) // {name: "Evan", surname: "Graham", job: "Barber"}
userWithJob.name = 'James'
console.log(user) // {name: "Evan", surname: "Graham"}
console.log(userWithJob) // {name: "James", surname: "Graham", job: "Barber"}let user = { name: 'Evan', surname: 'Graham' }
let jamesUser = { ...user, name: 'James' }
console.log(jamesUser) // {name: "James", surname: "Graham"}let obj = { key1: 'value1' }
let args = [...obj]
// TypeError: obj is not iterablefunction myFunction(x, y, z) {}
let args = [0, 1, 2]
myFunction(...args)
// myFunction(args[0], args[1], args[2]);
// myFunction(1, 2, 3);function myFunction(v, w, x, y, z) {}
let args = [0, 1]
myFunction(-1, ...args, 2, ...[3])
// myFunction(-1, args[0], args[1], [3][0]);
// myFunction(-1, 0, 1, 3);The
rest parametersyntax allows us to represent an indefinite number of arguments as an array.
function(a, b, ...theArgs) {
// ...
}function func(...args) {
console.log(args.length)
}
func() // 0
func(5) // 1
func(5, 6, 7) // 3
argumentsis an iterable (array-like), but not anArray
Array of arguments
function sortRestArgs(...theArgs) {
let sortedArgs = theArgs.sort()
return sortedArgs
}
console.log(sortRestArgs(5, 3, 7, 1)) // shows 1,3,5,7arguments built-in variable
function sortArguments() {
let sortedArgs = arguments.sort()
return sortedArgs // this will never happen
}
// throws a TypeError: arguments.sort is not a function
console.log(sortArguments(5, 3, 7, 1))
...is usefull to get "the rest of the arguments"
function filterByType(type, ...items) {
return items.filterByType(item => typeof item === type)
}
filterByType('boolean', true, 0, false) // => [true, false]
filterByType('number', false, 4, 'Welcome', 7) // => [4, 7]Spreading arguments
let values = [1, 3, '4', true, '8']
console.log(filterByType('string', ...values)) // ["4", "8"]let seasons = ['winter', 'spring', 'summer', 'autumn']
let [coldSeason, ...otherSeasons] = seasons
console.log(coldSeason) // => "winter"
console.log(otherSeasons) // => ["spring", "summer", "autumn"]Read the slides again, and we'll start a small quiz on operators.
/* 1 */ true && 3 == '3'
/* 2 */ false || (3 == '3')(/* 3 */ 3 != '3') || 3 === 3
/* 4 */ 'Cat' || 'Dog'
/* 5 */ 'Cat' && 'Dog'
/* 6 */ '' || 'Dog'
/* 7 */ !!'' && !!'Cat'(/* 8 */ 18 >= 18) ? 'adult' : 'minor'/* 1 */ true && (3 == '3') // true
/* 2 */ false || (3 == '3') // true
/* 3 */ (3 != '3') || (3 === 3)) // true
/* 4 */ "Cat" || "Dog" // "Cat"
/* 5 */ "Cat" && "Dog" // "Dog"
/* 6 */ "" || "Dog" // "Dog"
/* 7 */ !!"" && !!"Cat" // false
/* 8 */ (18 >= 18) ? "adult" : "minor" // "adult"let names = ['Evan', 'Tim', 'Roger', 'Monica']
delete names[2]
console.log(names)let names = ['Evan', 'Tim', 'Roger', 'Monica']
delete names[2]
console.log(names)
// ["Evan", "Tim", undefined, "Monica"]let animals = ['Dog', 'Cat', 'Rabbit', 'Mouse']
delete animals
console.log(animals)let animals = ['Dog', 'Cat', 'Rabbit', 'Mouse']
delete animals
console.log(animals)
// ["Dog", "Cat", "Rabbit", "Mouse"]let arr1 = [0, 4, 2]
let arr2 = [3, 1, 5]
arr1.push(...arr2)
console.log(arr1)let arr1 = [0, 4, 2]
let arr2 = [3, 1, 5]
arr1.push(...arr2)
console.log(arr1)
// [0, 4, 2, 3, 1, 5]let arr1 = [8, 7, 6, 14, 17]
let arr2 = [3, 1, 5, 3]
;[a, b, ...cd] = arr1
arr3 = [a, ...arr2, b, ...cd]
console.log(arr3)let arr1 = [8, 7, 6, 14, 17]
let arr2 = [3, 1, 5, 3]
;[a, b, ...cd] = arr1
arr3 = [a, ...arr2, b, ...cd]
console.log(arr3)
// [8, 3, 1, 5, 3, 7, 6, 14, 17]let str = 'javascript'
console.log([...str].join('|'))let str = 'javascript'
console.log([...str].join('|'))
// "j|a|v|a|s|c|r|i|p|t"String is iterable, so you can spread them.
let str = 'javascript'
let [a, b, , , c, ...d] = str
console.log(a, b, c, d)let str = 'javascript'
let [a, b, , , c, ...d] = str
console.log(a, b, c, d)
// "j"
// "a"
// "s"
// ["c", "r", "i", "p", "t"]let { prop: a = 5, prop2: { prop2: { nested: [, , b] } }, prop3: c = 10 } = {
prop: 'Hello',
prop2: {
prop2: { nested: ['a', 'b', 'c'] }
}
}
console.log(a, b, c)let { prop: a = 5, prop2: { prop2: { nested: [, , b] } }, prop3: c = 10 } = {
prop: 'Hello',
prop2: { prop2: { nested: ['a', 'b', 'c'] } }
}
console.log(a, b, c)
// "Hello"
// "c"
// 10