В Javascript есть много "хитростей" вокруг типов и преобразований типов, поэтому мне интересно, одинаковы ли эти 2 метода или есть какой-то угловой случай, который их отличает?
Ответы:
Они не полностью одинаковы, и на самом деле конструктор String, вызываемый как функция (ваш первый пример), в конце вызовет toStringметод переданного объекта, например:
var o = { toString: function () { return "foo"; } };
String(o); // "foo"
С другой стороны, если идентификатор ссылается на nullили undefined, вы не можете использовать toStringметод, он выдаст вам TypeErrorисключение :
var value = null;
String(null); // "null"
value.toString(); // TypeError
StringКонструктор вызывается как функция будет примерно эквивалентно:
value + '';
Правила преобразования типа от объекта -До- Примитивными подробно описано описаны на спецификации, на [[DefaultValue]]внутренней операции.
Кратко, при преобразовании из Объекта -До- строки , выполняются следующие шаги:
toStringметод.
resultэто примитив , вернитесь result, в противном случае перейдите к шагу 2.valueOfметод.
resultявляется примитивом , вернитесь result, в противном случае перейдите к шагу 3.TypeError.Учитывая приведенные выше правила, мы можем сделать пример задействованной семантики:
var o = {
toString: function () { return "foo"; },
valueOf: function () { return "bar"; }
};
String(o); // "foo"
// Make the toString method unavailable:
o.toString = null;
String(o); // "bar"
// Also make the valueOf method unavailable:
o.valueOf = null;
try {
String(o);
} catch (e) {
alert(e); // TypeError
}
Если вы хотите узнать больше об этом механизме, я бы порекомендовал взглянуть на ToPrimitiveи ToStringвнутренние операции.
Также рекомендую прочитать эту статью:
new String({toString: null})бросает TypeError.
String()и + ''теперь есть довольно существенная разница. String(Symbol())будет работать, но Symbol() + ''выдаст ошибку (и Symbol () передаст ложную охрану, в отличие от null и undefined, поэтому x && (x + '')теперь может вызывать ).
value.toString()вызовет ошибку, если valueимеет значение null. String(value)не должна.
Например:
var value = null;
alert(value.toString());
потерпит неудачу, потому что value == null.
var value = null;
alert(String(value));
должен отображать сообщение, читающее "null" (или подобное), но не произойдет сбой.
String(value)должен иметь тот же результат, что и value.toString()в любом случае, за исключением значений без таких свойств, как nullили undefined. ''+valueдаст тот же результат.
String () [ вызов конструктора ] в основном вызывает .toString ()
.toString () и String () могут вызываться для примитивных значений (число, логическое значение, строка) и в основном ничего особенного делать не будут:
истина => 'правда'
false => 'ложь'
17 => '17'
'привет' => 'привет'
Но при вызове этих функций для объектов все становится интересно:
если у объекта есть собственная функция .toString (), она будет вызываться, когда вам понадобится, чтобы этот объект обрабатывался как строка (явно / неявно)
let obj = {
myName:"some object",
toString:function(){ return this.myName; }
}
//implicitly treating this obj as a string
"hello " + obj; //"hello some object"
//OR (explicitly)
"hello " + String(obj) //calling the existent toString function
//OR
"hello " + obj.toString(); //calling toString directly
Кстати, если вы хотите рассматривать этот объект как число, в нем должна быть определена функция .valueOf () .
что, если у нас есть и то, и другое в одном объекте?
если мы хотим рассматривать этот объект как строку => используйте .toString ()
если мы хотим рассматривать этот объект как число => используйте .valueOf ()
что, если у нас есть только .valueOf () ?
.valueOf (), определенный внутри объекта, будет вызываться независимо от того, хотим ли мы обработать объект как строку или как число.
new String(value)при любом значении он всегда будет возвращать строковый объект.