Почему не работает функция прототипа valueOf?

let user1 = {
  valueOf() {
    console.log(20);
    return 10;
  }
};
console.log(`${user1}`); // [object Object]

// user1.__proto__.toString

let user2 = {
  toString() {
    console.log(20);
    return 10;
  }
};
console.log(+user2); // 20 10

// user2.__proto__.valueOf ??????????????


Почему не работает функция прототипа valueOf ?
  • Вопрос задан
  • 205 просмотров
Решения вопроса 1
Vlad_IT
@Vlad_IT Куратор тега JavaScript
Front-end разработчик
У вас перепутано немного. Объект user1 имеет переопределение функции valueOf, которая вызывается. при преобразовании в число. А user2 переопределение toString, которая вызывается при преобразовании в строку.
При `${A}` будет вызываться toString, а при +A будет valueOf (или если его нет, то toString)

console.log(`${user2}`); // Выведет 20 10, т.к. будет вызов user2.toString()
console.log(+user1); // Выведет 20 10 т.к. будет вызов user1.valueOf();
console.log(+user2); // Вывезет 20 10, у user2 нет valueOf, будет произведен вызов функции toString, результат которой будет преобразован в число.


Во втором случае у вас сработало потому, что в +user2 сначала смотрится valueOf, если его нет, используется toString. В первом же случае используется только toString, а у вас эта функция не переопределена.

А значение с __proto__ не будет меняться, т.к. вы его и не меняли, у вас же user1.__proto__ === Object.prototype
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
@abberati
frontend-разработчик
Она работает. Просто не вызывается вами.
Ответ написан
Комментировать
Lynn
@Lynn
nginx, js, css
Потому что есть toString

https://javascript.info/object-toprimitive
Ответ написан
Комментировать
dollar
@dollar
Делай добро и бросай его в воду.
Согласно спецификации:
  1. Сначала JS честно пытается вызывать valueOf.
  2. И находит его, но не в объекте, а в прототипе. И тот valueOf устроен очень просто - возвращает сам объект.
  3. Далее происходит проверка на примитивность результата. Если да, то этот результат и будет использован. Но user2 - это объект, и он явно не примитивен, так что JS переходит к следующему шагу.
  4. А следующий шаг - проверить метод toString. Если он есть, и это функция, то взывать его.
  5. Потом также смотрим, что он вернул. Здесь ваш метод возвращает 10, то есть число, а это примитивный тип.
  6. Таким образом, этот результат и возвращается и передается для дальнейшей обработки оператором +.
  7. Последний шаг редко срабатывает. До него доходит очередь, если даже toString не смог вернуть примитив. В этом случае произойдет исключение.


Иногда всё же можно добиться исключения, но это надо постараться. Пример:
let o={toString:e=>e=>1}; //Переопределить toString, чтобы убрать строку
console.log(+o);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы