preface
2 ==’2′, 1+2 == 1+’2′ is false. At this time should be a face of meng forced state, have to sigh js weak type of flexible people appalling, type conversion is so caught off guard. In practice, there are many instances where type conversions are involved, intentionally or unintentionally. Now that you want to use it, you need to grasp its principle, and it’s important to know why it’s important to know why it’s important.
Js variable type
JavaScript is weakly typed, which means that JavaScript variables have no predetermined type. And the type of a variable is the type of its value. That is, the current type of a variable is determined by its value. Hyperbole is that a string one second may be an array the next. In addition, when certain operations are performed, variables can be cast. The active type is explicit casting, and the other type is implicit casting. Such as:
var a = '1';
typeof a;//string
a =parseInt(a); // The display is converted to number
typeof a //number
a == '1' //true
Copy the code
The nature of weak typing can be as confusing as it is convenient. The premise of making full use of this feature is to master the principle of type conversion. Let’s take a look at the following.
Js data type
Two well-worn data types:
- The primitive type is Undefined, Null, String, Number, Boolean
- In addition to the object reference type, there is an ES6 new Symbol, which we will not discuss for now. For these five types of primitive types, sudden questions may not be complete, there is no need to memorize, you can think about the common variables for no and their corresponding values.
0 | Number |
---|---|
‘ ‘ | String |
false | Boolean |
null | Null |
undefined | Undefined |
The conversion rules are different for different data formats and we need to treat them separately.
Transformation rules
Since it is a rule defined by the specification, don’t ask why, first look at it and try to remember it. Is not always check out the big guy’s blog es5 specification. There are several types of transformations, and let’s take a look at the specifications. (This part of the conversion rules, you can skip, look at the following examples should be easier to accept back)
- Convert to the original value
- Convert to numbers
- Convert to string
ToPrimitive(convert to original value)
The ToPrimitive operator takes a value and an optional expected type as an argument. The ToPrimitive operator converts its value argument to a non-object type. If an object has the ability to be converted to more than one primitive type, an optional expected type can be used to indicate that type. Complete the conversion according to the table below
This definition seems a little dry. A conversion to a raw value is for reference data and is intended to be converted to a non-object type. For object, return the corresponding primitive type, which is determined by the desired type, which is actually the type we passed. It’s easier to look down here. The ToPrimitive method looks something like this.
/** * @obj Specifies the object to be converted to. * @type Specifies the original data type to be converted to
ToPrimitive(obj,type)
Copy the code
Type can be number or string, which are executed in a slightly different order. String:
- Call obj’s toString method, returning if it is raw, otherwise next
- Call the valueOf method of obj, as above
- Raises a TypeError exception
number:
- Call the valueOf method of obj, returning if it is original, otherwise next
- Call obj’s toString method, as above
- Raises a TypeError exception
It’s a matter of which method to call, because the expected data type is different, so if it’s a string, it’s a toString call. And vice versa. Of course, the type parameter can be null, in which case the default value of type is set according to the following rules
- If the object is Date, type is set to String
- Otherwise, type is set to Number
For the Date data type, we expect more of the string after the conversion time than the millisecond value. If the value is number, the corresponding millisecond value will be taken. Obviously, strings are used more. For other types of objects, the operation is based on the value type.
In general, ToPrimitive converts to a primitive type depending on type. The type parameter is optional. If specified, it converts to the specified type. When type type is specified, it depends on the following two conversions.
toNumber
In certain cases, the ToNumber method is used to convert the number operator to a value of numeric type according to the table below
For strings, there are more cases, so you just need to know the common ones. This is the same result as the direct call to Number(STR), which I won’t mention here, but is too much to mention. Note that when ToPrimitive is called, type is specified as number. The toString below is a string.
toString
The ToString operator converts its arguments ToString values according to the following table:
In fact, it is also very simple to understand, after all, it is a specification, borrow a picture from the big guy:
Although it’s something to memorize, there are some rules to follow. For raw values:
- Use Undefined, null, Boolean in quotes, such as ‘null’.
- Number has a longer specification, because it has a larger range and the common one is ‘1’ NaN which is ‘NaN’ which is basically the same thing as the one above and if it’s a negative number it returns a -+ string like ‘-2’ and I don’t care about anything else.
- The object is converted to its original value and then processed according to the above steps.
valueOf
When calling the valueOf method, take the following steps:
- Call ToObject to get an object O
- The original data type is converted to the corresponding built-in object, while the reference type remains unchanged
- Call this object (O) with the built-in valueOf method.
ValueOf implementations for different built-in objects:
- String => Returns a String value
- Number => Returns the Number value
- Date => returns a number, the time value, and the content of the string is implementation-dependent
- Boolean => Returns Boolean’s this value
- Object => Returns this
Make it a little clearer with the code
var str = new String('123')
/ / 123
console.log(str.valueOf())
var num = new Number(123)
/ / 123
console.log(num.valueOf())
var date = new Date(a)/ / 1526990889729
console.log(date.valueOf())
var bool = new Boolean('123')
//true
console.log(bool.valueOf())
var obj = new Object({valueOf:(a)= >{
return 1
}})
// Depends on internal implementations
console.log(obj.valueOf())
Copy the code
Arithmetic implicit conversion
All the abstractions mentioned above are intended to understand the concrete transformations here. For + operations, the rules are as follows:
- ToPrimitive() operation is performed
- Get the values after the left and right conversion respectively. If there is a String, it is ToString and concatenated.
- Everything else is ToNumber treated
- ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive: ToPrimitive
1+'2'+false
Copy the code
- I’m going to take the original value on the left-hand side, which is still Number
- If the middle is String, the toString operation is performed
- The left-hand conversion returns ‘1’ according to toString rules.
- We get the temp value ’12’
- Boolean values on the right and temp do the same
- If temp is string, Boolean is string’false’
- Concatenate the two and get ’12false’
Let’s look at a complicated one
var obj1 = {
valueOf:function(){
return 1}}var obj2 = {
toString:function(){
return 'a'}}/ / 2
console.log(1+obj1)
//1a
console.log('1'+ obj2)
//1a
console.log(obj1+obj2)
Copy the code
No matter how complicated it is, do it in the order above.
- 1+obj1
- Not on the left, number
- The right obj is converted to the base type, as type number
- The first call to valueOf() results in 1
- If you get the number twice, you add it up and you get 2
- 1+obj2
- As the number on the left
- The right side is also converted according to type to number
- Calling obj2.valueof () does not get the original value
- Call toString() return ‘a’
- According to the second rule, if there are strings, they are converted to strings for concatenation
- We get result 1A
- obj1+obj2
- ToPrimitive The default type is number
- Obj1.valueof () returns 1
- Obj2.valueof () does not get the original value
- Call toString() return ‘a’
- According to the second rule, if there are strings, they are converted to strings for concatenation
- We get result 1A
At this point, I think you’re pretty familiar with the type conversion of the + operation. Let’s take a look at another implicit type conversion
== Abstract equality comparison
The comparison falls into two broad categories,
- The same type
- Implicit conversions occur between different types. The rules are complicated, the specifications are long, and I’m not going to list them here, but you can look at the abstract equality algorithm. The string takes precedence over the number in equality comparison. Generally speaking, try to convert to number for processing, which is understandable, after all, the comparison is still expected to compare values. So the rule is something like this: for x == y
-
If x and y are both number, compare them directly
Nothing more to explain1= =2 //false Copy the code
-
If there are objects, ToPrimitive() type is converted to number and then compared
var obj1 = { valueOf:function(){ return '1'}}1 == obj2 //true // convert obj1 to its original value and call obj1.valueof () // return the original value '1' //'1'toNumber gets 1 and compares 1 == 1[] = =! []//true //[] as an object ToPrimitive gets" / /! [] converts to 0 as Boolean / / '= = 0 // Convert to 0==0 //true Copy the code
-
Boolean exists. Use ToNumber to convert Boolean to 1 or 0, and then compare
// Boolean first converts to number, then returns 1 //3 == 1 false //0 == 0 true 3= =true // false '0'= =false //true Copy the code
-
If x is string and y is number, x is converted to number for comparison
//'0' toNumber() gets 0 //0 == 0 true '0'= =0 //true Copy the code
conclusion
Refer to the article
The purpose of this article is to clarify the confusion for myself. It is really boring to write later, after all, there are more normative things, but it is better to know in depth than to memorize by rote. Please go to my blog. For some views that these belong to JS dross, should not be in-depth, how to say, combined with their own situation to judge it. My level is limited, throw a brick to attract jade to study together.