valueOf () по сравнению с toString () в JavaScript

В JavaScript каждый объект имеет valueOf () и toString () метод. Я думал бы, что toString () метод был вызван каждый раз, когда преобразование строк требуется, но по-видимому это превзойдено valueOf ().

Например, код

var x = {toString: function() {return "foo"; },
         valueOf: function() {return 42; }};
window.console.log ("x="+x);
window.console.log ("x="+x.toString());

распечатает

x=42
x=foo

Это кажется мне назад.. если бы x были комплексным числом, например, то я хотел бы, чтобы valueOf () дал мне свою величину, но каждый раз, когда я хотел преобразовать в строку, я захочу что-то как "a+bi". И я не хотел бы должным быть называть toString () явно в контекстах, которые подразумевали строку.

Это - просто способ, которым это?

111
задан brainjam 31 July 2016 в 16:46
поделиться

2 ответа

Причина, по которой ("x =" + x) дает "x = значение", а не "x = tostring", заключается в следующем. При оценке «+» javascript сначала собирает примитивные значения операндов, а затем решает, следует ли применять сложение или конкатенацию, в зависимости от типа каждого примитива.

Итак, как вы думаете, это работает

a + b:
    pa = ToPrimitive(a)
    if(pa is string)
       return concat(pa, ToString(b))
    else
       return add(pa, ToNumber(b))

, и это то, что на самом деле происходит

a + b:
    pa = ToPrimitive(a)
    pb = ToPrimitive(b)*
    if(pa is string || pb is string)
       return concat(ToString(pa), ToString(pb))
    else
       return add(ToNumber(pa), ToNumber(pb))

То есть toString применяется к результату valueOf, а не к вашему исходному объекту.

Дополнительную информацию см. В разделе 11.6.1 Оператор сложения (+) в спецификации языка ECMAScript.


* При вызове в строковом контексте ToPrimitive вызывает toString, но здесь дело обстоит не так, потому что '+' не применяет какой-либо контекст типа.

103
ответ дан 24 November 2019 в 03:04
поделиться

Вот еще немного подробностей, прежде чем я перейду к ответу:

var x = {
    toString: function () { return "foo"; },
    valueOf: function () { return 42; }
};

alert(x); // foo
"x=" + x; // "x=42"
x + "=x"; // "42=x"
x + "1"; // 421
x + 1; // 43
["x=", x].join(""); // "x=foo"

Функция toString - это , а не ] "превзойден" по valueOf в целом. Стандарт ECMAScript действительно хорошо отвечает на этот вопрос. Каждый объект имеет свойство [[DefaultValue]] , которое вычисляется по запросу. При запросе этого свойства интерпретатор также дает «подсказку» о том, какое значение он ожидает. Если подсказка String , тогда toString используется перед valueOf . Но если подсказка - Number , тогда сначала будет использоваться valueOf . Обратите внимание, что если присутствует только один или он возвращает не примитив, он обычно вызывает другой как второй вариант.

Оператор + всегда предоставляет подсказку Число , даже если первый операнд является строковым значением. Несмотря на то, что он запрашивает у x свое представление Number , поскольку первый операнд возвращает строку из [[DefaultValue]] , он выполняет конкатенацию строк.

Если вы хотите гарантировать, что toString вызывается для конкатенации строк, используйте массив и метод .join ("") .

(Однако ActionScript 3.0 немного изменяет поведение + .Если любой из операндов является строкой , он будет рассматривать ее как оператор конкатенации строк и использовать подсказку String при вызове [[DefaultValue]] . Итак, в AS3 этот пример дает «foo, x = foo, foo = x, foo1, 43, x = foo».)

73
ответ дан 24 November 2019 в 03:04
поделиться
Другие вопросы по тегам:

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