Всегда ли valueOf переопределяет toString в JavaScript?

Есть ли какое-либо выражение, где методом toString объекта неявно вызывается переопределение его метода valueOf?

В приведенных ниже примерах значение valueOf всегда вызывается неявно (переопределяя toString).

"4" + {
    toString: function () {
        return "4";
    },
    valueOf: function () {
        return 6;
    }
};    // => "46", was expecting "44"

4 + {
    toString: function () {
        return "6";
    },
    valueOf: function () {
        return 4;
    }
};    // => 8

4 + {
    toString: function () {
        return 6;
    },
    valueOf: function() {
        return "4";
    }
};    // => "44"

то есть:

Можем ли мы написать выражение, где toString неявно вызывается через valueOf (т.е. без явного вызова toString)?

3 ответа

Решение

Оператор + для объектов Date использует toString, а не valueOf. Также, если valueOf возвращает не примитивное значение, тогда вызывается метод toString. (JavaScript - полное руководство, раздел 3.14). Используя ваш пример:

var result = "4" + {
    toString: function () {
        return "4";
    },
    valueOf: function () {
        return this; // returning an object, not a primitive
    }
};

Результат сейчас 44.

Есть ли какое-либо выражение, где методом toString объекта неявно вызывается переопределение его метода valueOf?

Да, это случается всякий раз, когда ToString операция применяется к объекту, используя DefaultValue процедура с .toString() до .valueOf(),

Однако в ваших примерах вы использовали только оператор сложения, который является исключением из стандартного поведения. Поскольку он не только объединяет строки, но и суммирует числа, он всегда использует valueOf на обоих операндах перед проверкой, являются ли они строками. Смотрите примечание 1:

В вызовах ToPrimitive на этапах 5 и 6 подсказка не предоставляется. Все нативные объекты ECMAScript, кроме объектов Date, обрабатывают отсутствие подсказки, как если бы был указан номер подсказки; Объекты Date обрабатывают отсутствие подсказки, как если бы была указана строка подсказки. Хост-объекты могут обрабатывать отсутствие подсказки другим способом.

Итак, какие операции неявно используют ToString вместо намека ToPrimitive? Вот несколько примеров:

  • Все об именах собственности: in оператор, обозначение в скобках, Object.getOwnPropertyDescriptor, Object.defineProperty, hasOwnProperty
  • Функции, ожидающие строки в качестве аргументов: parseInt, parseFloat, encodeURI[Component], decodeURI[Component], [un]escape, Array::join, String::[last]indexOf, RegExp::exec
  • Function конструктор
  • Array::sort функция сравнения алгоритма по умолчанию
  • String методы конструктора и String при приведении this возражать против строки
  • RegExp конструктор
  • Error конструкторы
  • Множество других функций, не указанных в EcmaScript, но в DOM или где-то еще, например alert, XMlHTTPRequest::open, querySelector

Есть ли выражение

Да. Вот пример, который будет использовать toString:

alert({
    toString: function () {
        return "4";
    },
    valueOf: function () {
        return 6;
    }
});  // alerts "4"
Другие вопросы по тегам