valueOf и toString являются методами Object.prototype. Как правило, он редко вызывается напрямую, но эти два метода вызываются, когда объект используется для участия в операции. Думаю, у многих возникают следующие вопросы:
- Что имеет более высокий приоритет, valueOf или toString?
- Все ли сценарии вызывают valueOf и toString
Объяснение концепции
- valueOf: возвращает примитивное представление значения объекта.
- toString: возвращает строковое представление объекта
Прежде чем представить следующий контент, давайте разберемся с правилами преобразования. Следующие объяснения контента основаны на этой таблице правил:
правила преобразования valueOf
valueOf — это метод Object.prototype.Объекты из Object будут иметь этот метод, но многие встроенные объекты переопределяют этот метод, чтобы удовлетворить фактические потребности.
Говоря о примитивных значениях, мы должны говорить о примитивных типах.примитивный типследующим образом:
- Boolean
- Null
- Undefined
- Number
- String
Правила перезаписи для непримитивных значений (то есть объектов) следующие:
объект | значение возвращаемого значения |
---|---|
Array | сам массив |
Boolean | Логическое значение |
Date | Возвращает метку времени в миллисекундах |
Function | сама функция |
Number | числовое значение |
Object | сам объект |
String | строковое значение |
Следующие правила проверяются, если вас не волнует процесс проверки, вы можете просто посмотреть правила преобразования.
Рекомендуется взглянуть на процесс проверки, который может углубить понимание
объект преобразован в логический
- Прямое приведение к true (то же самое для типов-оболочек), без вызова valueOf и toString
преобразовать объект в число
Когда ожидается, что объект будет использоваться как число, например, участие в арифметических операциях и других операциях, методы valueOf и toString будут вызываться по очереди, когда объект преобразуется в число. Конкретные правила таковы:
- если объект имеет
valueOf
метод и возвращает исходное значение (строка, число, логическое значение, неопределенное значение, ноль), затем преобразует исходное значение в число (если преобразование завершается неудачей, оно возвращает NaN) и возвращает число - если объект имеет
toString
метод и возвращает исходное значение (строка, число, логическое значение, неопределенное значение, ноль), затем преобразует исходное значение в число (если преобразование завершается неудачей, оно возвращает NaN) и возвращает число - Преобразование не удалось, выдает TypeError
преобразовать объект в строку
- если объект имеет
toString
метод и возвращает исходное значение (строка, число, логическое значение, неопределенное, ноль), затем преобразует исходное значение в строку и возвращает строку - если объект имеет
valueOf
метод и возвращает исходное значение (строка, число, логическое значение, неопределенное, ноль), затем преобразует исходное значение в строку и возвращает строку - Преобразование не удалось, выдает TypeError
правила преобразования toString
объект | возвращаемое значение toString |
---|---|
Array | Строка, разделенная запятыми, например [1,2], возвращаемое значение toString равно "1,2" |
Boolean | "True" |
Date | Удобочитаемая строка времени, например «Вторник, 15 октября 2019 г., 12:20:56 GMT+0800 (стандартное время Китая)». |
Function | Строка исходного кода JS, объявляющая функцию |
Number | "числовое значение" |
Object | "[object Object]" |
String | "нить" |
Подтвердить преобразование объекта в примитив
ValueOf и ToString нечего смотреть на то, что можно сказать на ежедневное развитие редко вызывается напрямую, но когда мы возражаем для использования в качестве исходного значения преобразования, но процесс преобразования также немного запутался.
Объект преобразован в логический
Чтобы наглядно увидеть процесс конвертации внутри JS, я просто переписал и valueOf, и toString и добавил логи.
// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;
// 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this);
};
var a = {};
var b = new Boolean(false);
if (a) {
console.log(1);
}
if(b) {
console.log(2);
}
Вывод приведенного выше примера выглядит следующим образом:
1
2
valueOf и toString не вызываются в соответствии с правилами преобразования [object to boolean]
Объект преобразован в число
Пример 1
// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;
// 添加valueOf日志
Object.prototype.valueOf = function() {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function() {
console.log('toString');
return toString.call(this);
};
var a = {};
console.log(++a);
Результат выглядит следующим образом:
valueOf
toString
NaN
анализировать
- Метод valueOf возвращает сам объект, а не исходное значение, продолжайте выполнять
- Метод toString возвращает «[object Object]», которое является исходным значением (строкой), и преобразует строку в число NaN.
Пример 2
// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;
// 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return "1"; // 强制返回原始值
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this);
};
var a = {};
console.log(++a);
Результат выглядит следующим образом:
valueOf
2
анализировать
- valueOf возвращает исходное значение (строку), преобразует строку непосредственно в число и получает 1
преобразовать объект в строку
Преобразование происходит, когда ожидается, что объект будет использоваться как строка, например, когда строка объединяется со строкой и передается объект.
// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;
// 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this);
};
var a = {};
alert(a);
Результат выглядит следующим образом:
toString
// 弹出[object Object]
анализировать
- Вызывается метод toString, и возвращается строка «[object Object]», и, наконец, объект преобразуется в эту строку.
Пример 2
// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;
// 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return this;
};
var a = {};
alert(a);
Результат выглядит следующим образом:
toString
valueOf
Uncaught TypeError: Cannot convert object to primitive value
at 1.js:16
анализировать
- Вызовите метод toString, возвращаемое значение не является исходным значением, продолжайте выполнение
- Вызовите метод valueOf, возвращаемое значение не является исходным значением, продолжайте выполнение
- выдает TypeError
##[Special] Обработка при использовании оператора плюс для соединения строк и объектов
При тестировании преобразования объекта в строку было обнаружено, что следующий код ведет себя не так, как ожидалось:
// 保存原始的valueOf
var valueOf = Object.prototype.valueOf;
var toString = Object.prototype.toString;
// 添加valueOf日志
Object.prototype.valueOf = function () {
console.log('valueOf');
return valueOf.call(this);
};
// 添加toString日志
Object.prototype.toString = function () {
console.log('toString');
return toString.call(this);
};
console.log("a" + {});
Результат выглядит следующим образом:
valueOf
toString
a[object Object]
сомневаться
"a"+ {}
следует ожидать{}
При использовании в качестве строки сначала следует вызвать метод toString, но это не так.
В заключение
Выводы, сделанные на основе данных поиска, следующие:
- Если один из них является объектом, следуйте процессу преобразования объекта в исходное значение (объект Date напрямую вызывает toString для завершения преобразования, другие объекты преобразуются через valueOf, и если преобразование не удалось, вызывается toString)
- Если оба являются объектами, оба объекта преобразуются в строки после шага 1.
- Два числа, выполнить арифметические операции
- Две строки, соединенные напрямую
- Строка и число, непосредственно объединенные в строку
вопросы интервью
var a = {};
var b = {};
var c = {};
c[a] = 1;
c[b] = 2;
console.log(c[a]);
console.log(c[b]);
отвечать
Поскольку ключ объекта является строкой, поэтомуc[a]
а такжеc[b]
серединаa
а такжеb
Выполняется преобразование [объекта в строку].
Согласно правилам преобразования,a
а такжеb
преобразуются в[object Object]
,такc[a]
а такжеc[b]
Один и тот же ключ работает.
ответ输出两个2
, окончательная структура объекта c выглядит следующим образом:
{
'[object Object]':2
}