Яка різниця між String (value) та value.toString ()


105

У Javascript є багато "хитрощів" щодо типів та перетворень типів, тому мені цікаво, чи ці два методи однакові чи чи є якийсь кутовий випадок, який робить їх різними?

Відповіді:


123

Вони не зовсім однакові, і насправді конструктор 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 + '';

Правила перетворення типів з Object -to- Primitive детально описані у специфікації, [[DefaultValue]]внутрішній операції.

Коротко підсумовані, при перетворенні з Object -to- String здійснюються наступні кроки:

  1. Якщо є, виконайте toStringметод.
    • Якщо resultце примітивно , повернення result, інакше перехід до кроку 2.
  2. Якщо є, виконайте valueOfметод.
    • Якщо resultце примітивно , повернення result, інакше перейти до кроку 3.
  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внутрішніми операціями.

Я також рекомендую прочитати цю статтю:


1
Існує третій "спосіб", якщо ви називаєте це: new String(value)за будь-якого значення, він завжди поверне рядковий об'єкт.
Гербертуш

@ Гербертуш new String({toString: null})кидає а TypeError.
Константин Ван

З додаванням символів String()і + ''зараз є досить значна різниця. String(Symbol())запуститься, але Symbol() + ''видасть помилку (і Symbol () передасть захист фальси, на відміну від нульового та невизначеного, тому x && (x + '')тепер може кинути).
yeerk

24

value.toString()призведе до помилки, якщо вона valueє нульовою. String(value)не повинен.

Наприклад:

var value = null;
alert(value.toString());

не вдасться, тому що value == null.

var value = null;
alert(String(value));

повинно відображатися повідомлення з написом "null" (або подібне), але воно не вийде з ладу.


3
Я ніколи не бачив нульового виключення вказівника в JavaScript ... де ви це бачили?
Dagg Nabbit

приємно. було б ще приємніше з прикладом
mykhal

@no, @casablanca Виправлено. Я звик до Java. @mykhal Як це виглядає?
Джонатан

Він повертає рядок "null" :)
moefinley

1

String(value)повинні мати такий самий результат, як і value.toString()в кожному випадку, за винятком значень без властивостей, таких як nullабо undefined. ''+valueдасть такий же результат.


1

String () [ виклик конструктора ] в основному викликає .toString ()

.toString () і String () можна викликати примітивні значення (число, булеві, рядкові) і в основному нічого особливого не будуть робити:

true => 'true'

false => '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 (), визначений всередині об'єкта, буде називатися, чи хочемо ми обробляти об'єкт як рядок або як число

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.