Earlier, in the chapter Type Conversion for Primitives, we looked at type conversion, focusing on primitives. Now let's add objects to our slender picture of type conversion.
In this case there will be the following changes:
- In objects, numerical and string conversions can be redefined.
- If the operation requires a primitive value, then the object is first converted to a primitive, and then everything else.
In this case, a numerical transformation is used to transform to the primitive.
In order to better integrate them into the big picture, consider examples.
String conversion
String conversion is easiest to see if you display an object using alert
:
As you can see, the contents of the object is not displayed. This is because the standard string representation of the user object is the string "[object Object]"
.
This output object does not contain interesting information. Therefore, it makes sense to change it to something more useful.
If the object has a toString
method that returns a primitive, then it is used for conversion.
The toString
method is not required to return exactly the string.
Its result can be of any primitive type. For example, it can be a number, as in the example below:
Therefore, we call it here a "string conversion" , and not a "conversion to a string."
All objects, including embedded ones, have their own implementation of the toString
method, for example:
Numerical conversion
For the numerical transformation of an object, the valueOf
method is used, and if it is not, then toString
:
The valueOf
must return a primitive value, otherwise its result will be ignored. At the same time - not necessarily numeric.
Most built-in objects do not have such a valueOf
, so the numerical and string conversions work the same for them.
The exception is the Date
object, which supports both types of transformations:
If you look at the standard, then in 15.2.4.4 valueOf
defined for any objects. But he does nothing, just returns the object itself (non-primitive value!), And therefore is ignored.
Transformation to primitive
Most operations that expect a primitive value, when viewed as an object, first convert it to a primitive.
For example, an arithmetic operation or comparison > < >= <=
first converts an object into a primitive.
And then there is an operation with primitives, with subsequent transformations possible.
When converting an object to a primitive, a numerical transformation is used.
For example:
The example below demonstrates that despite the fact that the cast is “numerical” - its result can be any primitive value, not necessarily a number:
After the object is reduced to a primitive, there may be additional transformations. For example:
There is an exception: the Date
object is converted to a primitive using a string conversion. This can be encountered in the "+"
operator:
This exception is clearly spelled out in the standard and is unique.
In Java, you can create boolean values using the syntax new Boolean(true/false)
. You can also convert values to a boolean type by applying new Boolean
to them.
JavaScript also has a similar feature that returns an “object wrapper” for a boolean value. This feature is reserved for compatibility and is not used in practice, as it leads to strange results.
For example:
Why did the alert
start? After all, if
is false
... Check:
The fact is that new Boolean
is an object. In a logical context, it is certainly true
. Therefore, the first example works.
And the second example calls alert
, which converts an object to a string, and it becomes "false"
.
To convert a value to a boolean type, you need to use a double negative: !!val
or a direct call to Boolean(val)
.
Total
- When a object is converted to a string, its
toString
method is used. It must return a primitive value, and not necessarily just a string. The standard states that if there is no toString
, or if it returns not a primitive, but an object, then valueOf
is called, but usually there is a toString
.
- When numerically converting an object, the
valueOf
method is used, and if not, then toString
. valueOf
objects usually do not. - With an operation on an object that requires a primitive value, the object is first converted to a primitive. For this, a numerical conversion is used, the exception is the built-in
Date
object.
The complete transformation algorithm is in the EcmaScript specification, see clauses 11.8.5,11.9.3, as well as 9.1 and 9.3.
Importance: 5
If on the one hand there is an object, and on the other, it does not, then the object is first given.
In this case, the comparison means numerical cast. Arrays have no valueOf
, so toString
is called, which returns a list of elements separated by commas.
In this case, there is only one element - it is returned. So ['x']
becomes 'x'
. It turned out 'x' == 'x'
, right.
PS
For the same reason, equality is true:
[Open task in new window]
Importance: 5
Answers one by one.
-
alert(foo)
- Returns a string representation of the object using
toString
, i.e. "foo"
. -
alert(foo + 1)
- The
'+'
operator converts an object to a primitive using valueOf
, so the result is: 3
. -
alert(foo + '3')
- Same as the previous case, the object becomes a primitive
2
. Then there is the addition of 2 + '3'
. The operator '+'
when adding something with a string results in the second operand to the string, and then applies concatenation, so the result is the string "23"
.
[Open task in new window]
Importance: 5
Two objects are equal only when it is one and the same object.
In the first equality, two arrays are created, they are different objects, so they are unequal.
The answer to the second equality
[Open task in new window]
Importance: 5
2 | new Array(1)[0] + "" = "undefined" |
5 | [1,2] + [3,4] = "1,23,4" |
6 | [] + null + 1 = "null1" |
8 | ({} + {}) = "[object Object][object Object]" |
-
new Date(0)
is a date created in milliseconds and corresponding to 0ms from January 1, 1970 00:00:00 UTC. The minus operator converts the date back to the number of milliseconds, that is, to 0
. -
new Array(num)
when called with a single argument-number creates an array of a given length, without elements. Therefore, its null element is equal to undefined
; when added to a string, the string "undefined"
obtained. - Braces are the creation of an empty object, it does not have the property
'0'
. So the value will be undefined
.
Pay attention to the external, parentheses. If you remove them and run {}[0]
in the browser debugging console, it will be 0
, because {}
brackets will be perceived as an empty block of code, followed by an array. - The array is converted to the string
"1"
. The operator "+"
when adding with a string leads the second argument to the string - it means there will be "1" + "1" = "11"
. - Arrays are converted to a string and added together.
- The array is converted to the empty string
"" + null + 1
, the operator "+"
sees that the string on the left converts null
to the string, it turns out "null" + 1
, and as a result "null1"
. -
[[0]]
is the nested array [0]
inside the external [ ]
. Then we take the zero element from it, and then again. If this is not clear, then look at this example:
The square brackets after the array / object do not mean a different array, but take the element.
- Each object is converted to a primitive. The built-in Objects do not have the appropriate
valueOf
, so toString
used, so the resulting string representations of the objects are added together.
[Open task in new window]
Importance: 2
So that sum(1)
and sum(1)(2)
can be called with new brackets, the result of sum
should be a function.
But this function should also be able to turn into a number. To do this, give it the appropriate valueOf
. And if we want it to behave in the same way in a string context, then toString
.
A function that returns a sum
should accumulate a value on each call.
The most convenient way is to store it in the closure, in the variable currentSum
. Each call adds the next value to it:
A close look at the solution makes it easy to see that the sum
function only works once. It returns the function f
.
Then, each time the function is started, f
adds the parameter to the sum of the currentSum
stored in the closure, and returns itself.
The last line of f
no recursive call.
So that would be a recursion:
And in our case, we simply return the function itself, without calling anything.
This f
used the next time it is called, will return itself again, and as many times as necessary. Then, when used in a string or numeric context, it will trigger toString
, which will return the current sum of currentSum
.
Comments
To leave a comment
Scripting client side JavaScript, jqvery, BackBone
Terms: Scripting client side JavaScript, jqvery, BackBone