Как мы все знаем, в JS есть 7 типов данных:Undefined,Null,Boolean,Number,String,Symbolа такжеObject. Первые 6 являются основными типами,Objectявляется ссылочным типом.
"Операция преобразования типа"В статье говорилось, что, поскольку JS является языком со слабой типизацией, мы можем выполнять операции получения свойств ссылочного типа «должен иметь» для данных базового типа точно так же, как ссылочные типы.
Например, следующий код не выдаст ошибку:
var a = 1;
a.x = 2;
Во время выполнения приведенного выше кода происходит «операция упаковки». Читая спецификацию «ECMA-262», мы знаем, что браузер внутренне вызываетToObjectоперация, которая заключает примитивный тип в соответствующий ссылочный тип. например поставить1упаковано какnew Number(1).
Эта статья посвящена теме противоположной операции: ссылка на эти типы основных типов «перед другими», что происходит при выполнении операции? То есть «операции распаковки».
Например, следующий код не выдаст ошибку:
var a = 1;
var b = {};
console.log(a - b);
При выполнении операций вычитания над обычными объектами объекты необходимо преобразовать в числовые типы.Раздел 11.6.2 Ecma-262 Edition 5.1Спецификация оператора вычитания выглядит следующим образом:
The production AdditiveExpression : AdditiveExpression - MultiplicativeExpression is evaluated as follows:
- Let lref be the result of evaluating AdditiveExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating MultiplicativeExpression.
- Let rval be GetValue(rref).
- Let lnum be ToNumber(lval).
- Let rnum be ToNumber(rval).
- Return the result of applying the subtraction operation to lnum and rnum. See the note below 11.6.3.
Шаги 5 и 6 в приведенных выше операциях являются более важными и вызывают внутренние операции.ToNumber:
| Argument Type | Result |
|---|---|
| Undefined | NaN |
| Null | +0 |
| Boolean | The result is 1 if the argument is true. The result is +0 if the argument is false. |
| Number | The result equals the input argument (no conversion). |
| String | See grammar and note below. |
| Object | Apply the following steps: 1. Let primValue be ToPrimitive(input argument, hint Number). 2. Return ToNumber(primValue). |
Последняя строка, обработкаObject, выполните два шага: 1.ToPrimitive. 2.ToNumber.
а такжеToPrimitiveработая сToObjectОтносительно представление преобразуется в примитивный тип:
| Input Type | Result |
|---|---|
| Undefined | The result equals the input argument (no conversion). |
| Null | The result equals the input argument (no conversion). |
| Boolean | The result equals the input argument (no conversion). |
| Number | The result equals the input argument (no conversion). |
| String | The result equals the input argument (no conversion). |
| Object | Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8. |
В последней строке говорится, что когда объект преобразуется в примитивный тип, это значение по умолчанию для полученного объекта. используется внутренне[[DefaultValue]](hint), исходный текст спецификации цитируется следующим образом (дополнение: на английский в этой статье можно не обращать внимания, я подробно объясню):
When the [[DefaultValue]] internal method of O is called with hint String, the following steps are taken:
- Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
- If IsCallable(toString) is true then,
- Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
- If str is a primitive value, return str.
- Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf".
- If IsCallable(valueOf) is true then,
- Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.
- If val is a primitive value, return val.
- Throw a TypeError exception.
When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken:
- Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf".
- If IsCallable(valueOf) is true then,
- Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and an empty argument list.
- If val is a primitive value, return val.
- Let toString be the result of calling the [[Get]] internal method of object O with argument "toString".
- If IsCallable(toString) is true then,
- Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and an empty argument list.
- If str is a primitive value, return str.
Throw a TypeError exception.- When the [[DefaultValue]] internal method of O is called with no hint, then it behaves as if the hint were Number, unless O is a Date object (see 15.9.6), in which case it behaves as if the hint were String.
When the [[DefaultValue]] internal method of O is called with no hint, then it behaves as if the hint were Number, unless O is a Date object (see 15.9.6), in which case it behaves as if the hint were String.
Приведенный выше алгоритм говорит о том, что согласноhintЗначения обрабатываются по-разному, напримерhintдаStringПри вызове объектаtoStringметод, если возвращаемое значение является значением примитивного типа, верните значение, в противном случае вызовите метод объекта.valueOfметод, если возвращаемое значение является значением примитивного типа, вернуть значение. В противном случае сообщается об ошибке.
а такжеhintдаNumberПри изменении порядка звоните первымvalueOf, если его возвращаемое значение не является примитивным типом, то вызовитеtoString. Кроме того, в дополнение к объекту даты, если он не переданhint, его значение по умолчанию равноNumber, поэтому при преобразовании типов в JS предпочтительнееNumber.
Давайте рассмотрим несколько примеров:
var a = {
toString() {
return 3
},
valueOf() {
return '30'
}
};
console.log(a - 5); // 25
Операция вычитания используется здесь, в это времяhintдаNumber, поэтому сначала вызовите объектaизvalueOfметод, его возвращаемое значение'30'Является строковым типом, является примитивным типом. следовательноa - 5стал'30' - 5.
Посмотри снова:
var a = {
toString() {
return {}
},
valueOf: null
};
console.log(a - 5); // Uncaught TypeError: Cannot convert object to primitive value
объектa, его методvalueOfне является функцией, так что посмотрите на егоtoStringметод, который возвращает пустой объект, а не примитивный тип. Отсюда ошибка.
Другой пример:
var o = {
toString() {
return 'now is: '
},
valueOf: function() {
return "时间是:"
}
};
var d = new Date();
console.log(o + d); // 时间是:Mon May 06 2019 13:56:39 GMT+0800 (中国标准时间)
Здесь используется операция сложения:
The production AdditiveExpression : AdditiveExpression + MultiplicativeExpression is evaluated as follows:
- Let lref be the result of evaluating AdditiveExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating MultiplicativeExpression.
- Let rval be GetValue(rref).
- Let lprim be ToPrimitive(lval).
- Let rprim be ToPrimitive(rval).
- If Type(lprim) is String or Type(rprim) is String, then
Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)- Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim). See the Note below 11.6.3.
Среди них шаги 5 и 6 непосредственно получают основные типы по обе стороны от знака плюс. Не все прошло на данный моментhint, o — это обычный объект, поэтому по умолчаниюhintдаNumber,в использованииvalueOfВозвращаемое значение. в то время как d является объектом даты, по умолчаниюhintдаStringПредпочтительно, чтобыtoStringметод.然后根据第 7 步,采用的是字符串拼接方法。
Операция сложения, вот еще один пример:
var o = {
toString: function() {
return 2
}
};
console.log(o + o); // 4
Здесь особо нечего объяснять.
ToPrimitiveПомимо того, что они широко используются в четырех арифметических операциях, часто используются и реляционные операции. Например==работать. Другие типы преобразования и другие связанные знания оставлены для последующих статей.
На данный момент "распаковка" завершена.
Эта статья закончилась.
Портал «JavaScript Mini Book», всесторонне закладывающий прочную основу