The behaviour of Unary Plus and Unary Negation operators:
Are you sometimes think that how unary operators such as unary plus and unary negation process the operand behind the scene? Are you clueless in your coding and confused that how the conversion of values or data types happens under the hood, especially with unary operators such as unary plus and unary negation? This article will give the answer to all of your questions related to this topic and will reduce your anxiety :).
In javascript, there are many unary operators such as unary plus, unary minus, logical NOT, bitwise NOT etc. Since javascript is not strictly typed language, so when we apply operators on data types, coercion of the data types happens under the hood such as in the case of unary plus, the operand will be converted to number type. The same kind of coercion happens with the unary negation operator.
So, it is very much important to know what is happening under the hood in order to correctly predict the coercion of the data types so that you can be very confident in your coding.
In this article, I am going to discuss 2 different unary operators - unary plus and unary negation operators.
Since unary plus and unary negation internally use ToNumber conversion, so I will first discuss the rules for conversion of any value (data types) to number (data types) in javascript so that it would be piece of cake to calculate the corresponding number.
Rules for conversion of any value to the number:
I will assume that there is a provided value and there is a ToNumber function which will take the provided value as an argument and return the converted value. I am doing so to make it understand the conversion or coercion in an easy way.
- If provided value is of the
number
type, return it (returnthat number
). - If provided value is of
BigInt
orSymbol
type, throw TypeError. - If provided value is
undefined
, returnNaN
. - If provided value is
null
, return+0
which is0
. - If provided value is
true
, return1
and If provided value isfalse
, return0
. - If provided value is of
string
type- If the
string
contains only StringNumericLiteral- process the
string
and returns the correspondingnumber
value.
- process the
- else return
NaN
means if it contains NonStrNumericLiteral, then returnNaN
.
- If the
- If provided value is of
object
type- then convert it into the corresponding
primitive value
and then convert thatprimitive
tonumber
.
- then convert it into the corresponding
I will also list the rule for conversion from object to primitive to make the process clear.
Rules for conversion of Object to Primitive
In this conversion also, I will assume that there is a provided value of the type object
and a ToPrimitive function that will take the provided value as an argument and return the converted value.
- First check if the object is having
valueOf
andtoString
methods, If no, throw Error. - Check the value of the result of invoking the
valueOf
method. If it is not theobject
type, then return the result otherwise move to step 3. - Check the value of the result of invoking
the toString
method. If it is not theobject
type, then return the result otherwise throw Error.
Now we know the rules for used conversion in the process, we can now go to the definition and corresponding examples for unary plus and unary negation operators.
Unary plus operator ( + ) :
The unary plus operator is a unary operator that converts the operand to number type if that is not already. That’s all it does. So we can say that the unary plus operator is the fastest way to convert any value into the number type.
Syntax:
// +operandor// +expression
This is the syntax for the unary plus operator. The unary plus operator can be applied to an operand or expression.
Execution step:
Now comes the execution step for the evaluation of unary plus
- The first operand or expression will be evaluated
- Then unary plus ( + ) operator will convert that evaluated value into the number.
For example:
console.log(+("john doe" + 1))// These are execution steps// 1. +("john doe" + 1)// 2. +("john doe1")// 3. NaN// logs NaN as result.
Common examples:
console.log(+[]) // 0console.log(+[""]) // 0console.log(+[null]) // 0console.log(+[undefined]) // 0console.log(+[0]) // 0console.log(+[NaN]) // NaNconsole.log(+["abc"]) // NaNconsole.log(+[[]]) // 0console.log(+[{}]) // NaNconsole.log(+{}) // NaNconsole.log(+{ a: "b" }) // NaNconsole.log(+true) // 1console.log(+false) // 0console.log(+0) // 0console.log(+1) // 1console.log(+1.23) // 1.23console.log(+-1.23) // -1.23console.log(+-0.23) // -0.23console.log(+NaN) // NaNconsole.log(+null) // 0console.log(+undefined) // NaNconsole.log(+"") // 0console.log(+"abc") // NaNconsole.log(+"123") // 123console.log(+"0") // 0console.log(+" ") // 0console.log(+" 123 ") // 123console.log(+" 1.23e10 ") // 12300000000console.log(+" 1.23e10 + ") // NaNconsole.log(+function abc() {}) // NaNconst sym = Symbol("1")console.log(+sym) // Throw TypeErrorconsole.log(+2n) // Throw TypeError
Unary negation operator ( - ) :
The unary negation operator is the unary operator that when applied to some operand, it tries to convert the operand to the numeric value and then negate it. After the conversion of the operand, if it is of number type, then it negates that number. After the conversion of the operand, if it is of BigInt type, then it does the corresponding negation of that Big Int.
Syntax:
// -operandor// -expression
As you can see in the above code block, that is the syntax for the unary negation operator. A unary negation operator can be applied to an operand or expression.
Execution Step:
Now comes the execution step for the evaluation of unary negation
- The first operand or expression will be evaluated
- Then unary negation ( - ) operator will convert that evaluated value into the numeric type ( either in number type or in BigInt type ).
- Then that numeric value will be negated
For example:
console.log(-(10 - "2"))// These are execution steps// 1. -(10 - "2")// 2. -(8)// 3. -8// logs -8 as result.
Common examples:
console.log(-[]) // -0console.log(-[""]) // -0console.log(-[null]) // -0console.log(-[undefined]) // -0console.log(-[0]) // -0console.log(-[NaN]) // NaNconsole.log(-["abc"]) // NaNconsole.log(-[[]]) // -0console.log(-[{}]) // NaNconsole.log(-{}) // NaNconsole.log(-{ a: "b" }) // NaNconsole.log(-true) // -1console.log(-false) // -0console.log(-0) // -0console.log(-1) // -1console.log(--0.23) // Syntax Errorconsole.log(-1.23) // -1.23console.log(-NaN) // NaNconsole.log(-null) // -0console.log(-undefined) // NaNconsole.log(-"") // -0console.log(-"abc") // NaNconsole.log(-"123") // -123console.log(-"0") // -0console.log(-" ") // -0console.log(-" 123 ") // -123console.log(-" 1.23e10 ") // -12300000000console.log(-" 1.23e10 + ") // NaNconsole.log(-function abc() {}) // NaNconst sym = Symbol('1');console.log(-sym) // Throw TypeErrorconsole.log(-2n) // -2n. It doesn't throw TypeError as the unary plus throw.
This is how unary plus and unary negation operators behave under the hood. I hope that now you are confident enough to predict the result just by seeing it and calculating it in your mind.
If you wanna check these rules, you can go to ECMAScript language specification - https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-unary-plus-operator and https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-unary-minus-operator.
I hope that you have liked the article.
Keep coding and keep solving problems.