One place for hosting & domains

      JavaScript Unary Operators: Simple and Useful


      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).

      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 { fries: 1 }
      
      // 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(voidResult);                             // 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="https://www.digitalocean.com/community/tutorials/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="https://www.digitalocean.com/community/tutorials/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
      logical-and && x < 10 && y > 1
      logical-or
      conditional ?: (age < 18) ? “Too young”:“Old enough”
      assignment = += -= *= /= %= <<= >>= >>>= &= ^= =
      *comma * , b = 3, c = 4



      Source link