Plus + operator
In JavaScript, the rule of addition is actually simple, in only two cases:
- Add numbers and Numbers
- Add a string and a string
All other types of values are automatically converted to these two types of values. In order to figure out how this implicit conversion works, we first need to understand some basic knowledge.
Let's review it quickly. In JavaScript, there are two kinds of values:
- Original Value (Primitives)
- Undefined
- Null
- Boolean
- Number
- String
- Object Value (objects): Except for the original value, all other values are values of the object type, including arrays (array) and functions (function).
Type conversions
The addition operator triggers three types of conversions:
- Convert to original value
- Convert to Digital
- Convert to String
Convert a value to the original value by Toprimitive ()
The abstract operation inside the JavaScript engine toprimitive () has such a signature:
Toprimitive (Input,preferredtype?)
The optional parameter Preferredtype can be number or String. It only represents a conversion preference, and the conversion result must not necessarily be the type that the parameter refers to (Khan), but the conversion result must be a primitive value. If Preferredtype is marked as number, the following action is taken to convert the input
- If input is a raw value, it is returned directly.
- Otherwise, if input is an object. The Obj.valueof () method is called. If the return value is an original value, the original value is returned.
- Otherwise, call the Obj.tostring () method. If the return value is an original value, the original value is returned.
- Otherwise, the TypeError exception is thrown.
If Preferredtype is marked as String, the second and third steps of the conversion operation are reversed. If this parameter is not preferredtype, the value of Preferredtype is automatically set according to this rule:
- Object of Date type is set to String
- Other types of values are set to number
Convert a value to a number by Tonumber ()
The table below explains how Tonumber () converts the original value to a number
Parameters |
Results |
Undefined |
NaN |
Null |
+0 |
Boolean |
True is converted to 1,false to +0 |
Number |
No conversion required |
String |
Parsed by a string into a number. For example, "324" is converted to 324 |
If the value entered is an object, then toprimitive (obj, number) is called first to convert the object to the original value, and then the original value is converted to a digit at call Tonumber ().
Convert a value to a string by ToString ()
The following table explains how ToString () converts the original value to a string.
Parameters |
Results |
Undefined |
"Undefined" |
Null |
"NULL" |
Boolean |
"True" or "false" |
Number |
Number as a string. For example, "1.765" |
String |
No conversion required |
If you enter a value that is an object, you first call toprimitive (obj, string) to convert the object to the original value, and then call ToString () to convert the original value to a string.
Practice a bit
The following object allows you to see the conversion process inside the engine.
var obj = {valueof:function () {Console.log ("valueOf"); return {};//Not a primitive},tostring:function () {Console.log ( "ToString"); return {}; Not a Primitive}}
When number is called as a function (rather than as a constructor call), the Tonumber () operation is called inside the engine:
> Number (obj) Valueoftostringtypeerror:cannot convert object to primitive value
Addition
There is an addition operation like the following.
Value1 + value2
In the calculation of this expression, the internal procedure is like this
- Convert two operands to the original value (the following is the pseudo-code for mathematical notation, not the JavaScript code that can be run):
PRIM1: = toprimitive (value1) prim2: = Toprimitive (value2)
Preferredtype is omitted, so the value of the Date type takes String, and the value of the other type takes number.
- If either PRIM1 or PRIM2 is a string, the other is converted to a string, and then the result of the two string connection operation is returned.
- Otherwise, convert both PRIM1 and prim2 to numeric types, returning their and.
The expected results
When you add two arrays, the result is exactly what we expect:
> [] + []
[] is converted to a primitive value: first try the ValueOf () method, which returns the array itself (this):
> var arr = [];> arr.valueof () = = = Arrtrue
At this point the result is not the original value, so call the ToString () method and return an empty string (string is the original value). Therefore, the result of [] + [] is actually a connection of two empty strings.
By adding an array and an object, the results still match our expectations:
> [] + {} ' [Object Object] '
Parse: When you convert an empty object to a string, the following results are generated.
> String ({}) ' [Object Object] '
So the final result is to connect the "" and "[Object Object]" two strings together.
More objects are converted to the original value example:
> 5 + new Number (7) 12> 6 + {valueof:function () {return 2}}8> "abc" + {tostring:function () {return "Def" }} ' ABCdef '
Unexpected results.
If the first operand of the + addition operation is an empty object literal, there will be a bizarre result (running results in Firefox console):
> {} + {}nan
The reason for this problem is that JavaScript interprets the first {} as an empty code block and ignores it. NaN is actually the result of the expression +{} calculation (+ PLUS sign and second {}). The + plus sign you see here is not a two-dollar operator "addition," but rather a unary operator that converts the operand following it to a number, exactly as the number () function. For example:
> + "3.65" 3.65
The following expression is its equivalent form:
+{}number ({}) Number ({}.tostring ()) //{}.valueof () isn ' t primitivenumber ("[Object Object]") NaN
Why is the first {} parsed into a code block? Because the entire input is parsed into a statement: If the opening brace appears at the beginning of a statement, the opening brace is parsed into the beginning of a block of code. So, you can also fix the result by forcing the input to parse into an expression: we expect it to be an expression, and the result is parsed into a statement.
> ({} + {}) ' [Object Object][object Object] '
The parameters of a function or method are also parsed into an expression:
> Console.log ({} + {}) [Object Object][object Object]
You should not be surprised at the results of the calculations below, as explained above:
> {} + []0
Once explained, the above input is parsed into a block of code followed by an expression +[]. The steps for conversion are this:
+[]number ([]) number ([].tostring ()) //[].valueof () isn ' t primitivenumber ("") 0
Interestingly, the REPL of node. js, when parsing similar inputs, is different from the parsing results of Firefox and Chrome (as with node. js using the V8 engine). The following input is parsed into an expression that is more consistent with our expectations:
> {} + {} ' [Object Object][object object] ' > {} + [] ' [Object Object] '
The Plus + operator in JS is detailed