JavaScript Unary Operators: Simple and Useful

A simple and useful introduction to javascript unary operators.

Related Course

Get Started with JavaScript for Web Development

JavaScript is the language on fire. Build an app for any platform you want including website, server, mobile, and desktop.

You might have come across things like i++, --i in loops or ! when writing conditions. Ever wondered how these operations work? Well, these are unary operators and we are going to take an in-depth look into how they work.

What is an operator?

Operator-operand Mathematically, an operation is a calculation on one or more values called operands mapping to an output value. An operator is a symbol/sign that maps operands to output values.

What is an unary operator?

A unary operator is one that takes a single operand/argument and performs an operation.

A unary operation is an operation with only one operand. This operand comes either before or after the operator. Unary operators are more efficient than standard JavaScript function calls. Additionally, unary operators can not be overridden, therefore their functionality is guaranteed.

Summary of all unary operators

Operator Explanation
Unary plus (+) Tries to convert the operand into a number
Unary negation (-) Tries to convert the operand into a number and negates after
Logical Not (!) Converts to boolean value then negates it
Increment (++) Adds one to its operand
Decrement (--) Decrements by one from its operand
Bitwise not (~) Inverts all the bits in the operand and returns a number
typeof Returns a string which is the type of the operand
delete Deletes specific index of an array or specific property of an object
void Discards a return value of an expression.

Unary plus (+)

This operator precedes the operand and tries to convert it to a number.

It can convert all string representations of numbers, boolean values(true and false) and null to numbers. Numbers will include both integers, floats, hexadecimal, scientific (exponent) notation and Infinity.

If the operand cannot be converted into a number, the unary plus operator will return NaN.

Examples:

    +3                                   // returns 3
    +'-3'                                // returns -3
    +'3.14'                              // returns 3.14
    +'3'                                 // returns 3
    +'0xFF'                              // returns 255
    +true                                // returns 1
    +'123e-5'                            // returns 0.00123
    +false                               // returns 0
    +null                                // returns 0
    +'Infinity'                          // returns Infinity
    +'infinity'                          // returns NaN
    +function(val){  return val }        // returns NaN

The illustration above clearly shows how the + operator will behave when applied to different data types.

  • Numbers will not be altered.
  • A string notation of a number e.g '3' is converted to that number (3).
  • Boolean value true is converted to a 1 and false to 0.
  • Other types e.g functions and objects are converted to NaN.

Note

An object can only be converted if it has a key valueOf and it's function returns any of the above types.

+{
  valueOf: function(){
    return '0xFF'
  }
}
//returns 255

Unary negation (-)

It also precedes the operand and converts non-numbers data types to numbers like unary plus, however, it performs an additional operation, negation.

Unary plus is considered the fastest and preferred way of making conversions because it doesn't perform any additional operation. Both the unary negation and plus perform the same operation as the Number() function for non-numbers.

Examples:

    -3                               // returns -3
    -'-3'                            // returns 3
    -'3.14'                          // returns -3.14
    -'3'                             // returns -3
    -'0xFF'                          // returns -255
    -true                            // returns -1
    -'123e-5'                        // returns -0.00123
    -false                           // returns -0
    -null                            // returns -0
    -'Infinity'                      // returns -Infinity
    -'infinity'                      // returns NaN
    -function(val){  return val }    // returns NaN
  -{                                 
    valueOf: function(){
      return '0xFF'
    }
  }                                //returns -255

Logical Not (!)

This operator comes before the operand. It converts the operand into it's boolean equivalent before negating it.

Examples:

!false        // returns true
!NaN          // returns true
!0            // returns true
!null         // returns true
!undefined    // returns true
!""           // returns true
!true         // returns false
!-3           // returns false
!"-3"         // returns false
!42           // returns false
!"42"         // returns false
!"foo"        // returns false
!"true"       // returns false
!"false"      // returns false
!{}           // returns false
![]           // returns false
!function(){} // returns false

The above illustration demonstrates how logical not returns false if the operand can be converted to true, if not it returns false.

You can use double negation(!!)

Let us take a look at a more awesome example:

!!'hi' === true  // returns true
!!1 === true    // returns true
!!0 === false  // returns true

Why true? So we execute from right to left.

!'hi'  //returns false

Then:

!false //returns true

Thus:

true === true //returns true

Increment (++)

This operator adds one to its operand and returns the result.

It can be used as a postfix or prefix operator.

  • Postfix : - meaning the operator comes after the operand(y++). This returns the value before incrementing.
  • Prefix: - the operator comes before the operand (++y). Using it as a prefix, returns the value after incrementing.

Examples:

Postfix

x = 4      // x=4
y = x++    // y = 4 and  x = 5
// y is set to the value before incrementing and it adds 1 to x

// Be careful about resetting values when using postfix
var a = 5     // a = 5
a = a++       // a = 5
// a is set to the value before incrementing

Prefix

x = 4      // x=4
y = ++x    // y = 5 and  x = 5
// y is set to the value after incrementing and it adds 1 to x

var a = 5     // a = 5
a = ++a       // a = 6
// a is set to the value after incrementing

Decrement (--)

The decrement operator subtracts one from its operand.

It returns a value before decrementing if it is postfix. Prefixing it returns the value after decrementing.

Examples:

Postfix

var a = 5     // a = 5
a = a--       // a = 5
// a is set to the value before incrementing

x = 4      // x=4
y = x--    // y = 4 and  x = 3
// sets y to the value before decrementing and it removes 1 from x

Prefix

var a = 5  // a = 5
a = --a    // a = 4
// a is set to the value after incrementing

x = 4      // x=4
y = --x    // y =3 and  x = 3
// sets y to the value after incrementing and it adds 1 to x

Bitwise not (~)

Performs a binary NOT operation, by inverting all the bits in the operand and return a number.

A bitwise not on a number results in: -(x + 1).

a Not a
0 1
1 0

Examples:

~2                                  //returns -3
~'2'                                //returns -3
~'-3'                               // returns 2
-'-3.14'                            // returns 2
~'-3.54'                            // returns 2
~'0xFF'                             // returns -256
~true                               // returns -2
~'123e-5'                           // returns -1
~false                              // returns -1
~null                               // returns -1
~'Infinity'                         // returns -1
~'infinity'                         // returns -1
~function(val){  return val }       // returns -1
~{                                 
    valueOf: function(){
        return '0xFF'
    }
}                                  //returns -256

The table below takes a deeper look into how this operation is performed.

(base 10) (base 2) Not (base 2) Not (base 10)
2 00000010 11111101 -3
1 00000001 11111110 -2
0 00000000 11111111 -1
-1 11111111 00000000 0
-2 11111110 00000001 1
-3 11111101 00000010 2

typeof

This operator comes before the operand. It returns a string indicating the data type of the operand.

Examples:

typeof 2                                       // returns 'number'
typeof -3.14                                   // returns 'number'
typeof 0xFF                                    // returns 'number'
typeof 123e-5                                  // returns 'number'
typeof true                                    // returns 'boolean'
typeof false                                   // returns 'boolean'
typeof null                                    // returns 'object'
typeof Infinity                                // returns 'number'
typeof '2'                                     // returns 'string'
typeof '-3'                                    // returns 'string'
typeof 'infinity'                              // returns 'string'
typeof Date()                                  // returns 'string'
typeof [1,2,3]                                 // returns 'object'
typeof {hi: 'world'}                           // returns 'object'
typeof function(val){  return val }            // returns 'function'
typeof {                                 
    valueOf: function(){
        return '0xFF'
    }
}                                              // returns 'object'
typeof undefined                               // returns 'undefined'
typeof hi                                      // returns 'undefined'
typeof NaN                                     // returns 'number'
typeof new Date()                              // returns 'object'
typeof /ab+c/                                  // returns 'object'
typeof new RegExp('ab+c')                      // returns 'object'
typeof document                                // returns 'undefined'      

delete:

It also comes before the operand. It deletes values of a specific index of an array and a specific property of an object.

It returns true if it successfully deleted the property or if the property does not exist. It returns false if it fails to delete an item.

Delete does not have any effect on both functions and variables. Let's look at the following examples.

// Deleting a variable
var hi = 1;
delete hi;          // returns false
console.log(hi);    // returns 1

// Deleting a function
function yo(){ };
delete yo;           // returns false
console.log(yo);     // returns function foo(){ }

// Deleting an object
var pub = {bar: '1'}
delete pub           // returns false
console.log(pub);    // returns {bar: '1'}

//Deleting an array
var code = [1,1,2,3,5]
delete code          // returns false
console.log(code);   //  [1,1,2,3,5]

Objects

As earlier stated, it deletes the property or the whole object. Examples:

// Deleting a property with the literal notation
var fruits = {1: 'apple', 2: 'mango'}
delete fruits[1]             // returns true
console.log(fruits);         // returns { '2': 'mango' }
console.log(fruits[1]);      // returns undefined

// Deleting a property with the dot notation
var pub = { bar: "42" };
delete pub.bar;              // returns true
console.log(pub);            // returns {}

// Deleting a property that does not exist
var lunch = { fries: 1 };
delete lunch.beans;          // returns true
console.log(lunch);          // returns {}

// Deleting a non-configurable property of a predefined object
delete Math.PI;              // returns false  
console.log(Math.PI);        // returns 3.141592653589793

Non-Configurable properties

Delete has no effect on an object property that is as non-configurable. It will always return false. In strict mode, this will raise a SyntaxError.

Examples:

// When Non Configurable
var Person = {};
Object.defineProperty(Person, 'name', {  value: 'Scot', configurable: false })
// Defines an object property and sets it to non-configurable
console.log(Person.value);                                    // returns 'Scot'
delete Person.value                                           // returns false
console.log(Person.value);                                    // returns 'Scot'

// When configurable
var b = {};
Object.defineProperty(Person, 'name', {  value: 'Scot', configurable: true })
console.log(b.value);                                    // returns 'Scot'
delete b.value                                           // returns true
console.log(b.value);                                    // returns undefined

Read more about defineProperty()

var, let and const create non-configurable properties that cannot be deleted with the delete operator:

Example:

var num = 1;
// We can access this global property using:
Object.getOwnPropertyDescriptor(window, 'num')  
// returns { value: 'XYZ',
//           writable: true,
//           enumerable: true,
//           configurable: false }  
delete num;                                     // returns false
// Node
Object.getOwnPropertyDescriptor(global, 'num')
// returns { value: 'XYZ',
//           writable: true,
//           enumerable: true,
//           configurable: false }
// regular objects
var lunch = { fries: 1 };                                                                                   
Object.getOwnPropertyDescriptor(lunch, 'fries')
// returns { value: 1,
//           writable: true,
//           enumerable: true,
//           configurable: true }

Notice that the var keyword is marked as non-configurable

Arrays

Arrays are considered type object in javascript. Thus this method will work on them.

Examples:

// Deleting values of an array index
var lol=[20,30,40];
console.log(lol.length);     // returns 3
delete lol[2]                // returns true
console.log(lol);            // returns [ 20, 30,  ]
console.log(lol[2]);         // returns undefined
console.log(lol.length);     // returns 3

Note

The delete operator will only delete the value and not the index of the array. It will leave the value of that particular index as undefined. This is why the length does not change.

strict mode

In strict mode, delete throws a SyntaxError due to the use of direct reference to a variable, a function argument or a function name.

‘use strict’
var fruits = {1:'mango', 2:'apple'};
delete fruits;
// Output: Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

function Person() {
 delete name;             // SyntaxError
 var name;        
}

function yo() {
}

delete yo; // SyntaxError

Here are a few pointers to always consider when using delete:

  • Trying to delete a property that does not exist, delete will return true but will not have an effect on the object.

  • Delete only affects object own properties. This means if a property with the same name exists on the object's prototype chain, then delete will not affect it. After deletion, the object will use the property from the prototype chain.

  • Variable declared var, let and const cannot be deleted from the global scope or from a function's scope.

    • Meaning:- Delete cannot delete any functions in the global scope or in the function scope.
    • Delete works on functions which are part of an object (apart from the global scope).
  • Non-configurable properties cannot be removed.

  • Delete does not work on any of the built-in objects like Math, Array, Object or properties that are created as non-configurable with methods like Object.defineProperty().

Void operator:

It precedes an operation. It discards the return value of an expression, meaning it evaluates an expression but returns undefined.

Void operator's main purpose is to return undefined. The void operator specifies an expression to be evaluated without returning a value.

The void operator is used in either of the following ways: void (expression) void expression

Note:

The void operator is not a function, so () are not required, but it is good style to use them according to MDN

Example:

void 0                                              // returns undefined
var hi = function () {
    console.log('Yap')
    return 4;
}
var result = hi()                                   // logs 'Yap' and returns 4
console.log(result);                                // returns 4

var voidResult = void (hi())                        // logs 'Yap' and returns undefined
console.log(result);                                // returns undefined

The void operator can be used to specify an expression as a hypertext link. The expression is evaluated but is not loaded in place of the current document.

Some more examples

<a href="javascript:void(0)">Click here to do nothing</a>

The code above creates a link that does nothing when a user clicks it. This is because void(0) evaluates to undefined.

<a href="javascript:void(document.form.submit())">
Click here to submit</a>

The code creates a link that submits a form when the user clicks it.

Conclusion

Always consider the order of operations when dealing with more than one operator. This is good practice in mitigating unforeseen bugs.

Here is a brief table that shows the order of precedence in operations when using Javascript. Operands on the same level have the same order of precedence.

Operator type Operators Example
member . [] [1,2,3]
call / create instance () new var vehicle = new Vehicle();
negation/increment ! ~ - + ++ -- typeof void delete typeof [1,2,2]
multiply/divide * / % 3 % 3
addition/subtraction + - 3 + 3
bitwise shift << >> >>> 9 << 2
relational < <= > >= in instanceof [1] instanceof Array
equality == != === !== void(0) === undefined
bitwise-and & 5 & 1
bitwise-xor ^ 5 ^ 1
bitwise-or | 5 | 1
logical-and && x < 10 && y > 1
logical-or || x == 5 || y == 5
conditional ?: (age < 18) ? "Too young":"Old enough"
assignment = += -= *= /= %= <<= >>= >>>= &= ^= |= x = 8
comma , b = 3, c = 4

Esther Dama Kahindi

I am passionate about making an impact in people's life. I'm a trained Computer Scientist who loves life, on a journey to discover what computing has to offer.Currently a Software Developer at Andela.