Jaka jest różnica między String (value) a value.toString ()


105

Javascript ma wiele "sztuczek" dotyczących typów i konwersji typów, więc zastanawiam się, czy te dwie metody są takie same, czy też istnieje jakiś narożnik, który je odróżnia?

Odpowiedzi:


123

Nie są one całkowicie takie same, a właściwie konstruktor String wywołany jako funkcja (Twój pierwszy przykład) na końcu wywoła toStringmetodę przekazanego obiektu, na przykład:

var o = { toString: function () { return "foo"; } };
String(o); // "foo"

Z drugiej strony, jeśli identyfikator odnosi się do metody nulllub undefinednie możesz jej użyć toString, będzie to TypeErrorwyjątek :

var value = null;
String(null);     // "null"
value.toString(); // TypeError

StringKonstruktor nazywa się funkcją byłaby grubsza odpowiada:

value + '';

Reguły konwersji typu z Object -to- Primitive są szczegółowo opisane w specyfikacji, czyli [[DefaultValue]]operacji wewnętrznej.

Krótko podsumowane podczas konwersji z klasy Object -to- ciąg , z następujących kroków:

  1. Jeśli to możliwe, wykonaj toStringmetodę.
    • Jeśli resultjest to prymityw , wróć result, w przeciwnym razie przejdź do kroku 2.
  2. Jeśli to możliwe, wykonaj valueOfmetodę.
    • Jeśli resultjest to prymityw , wróć result, w przeciwnym razie przejdź do kroku 3.
  3. Rzuć TypeError.

Biorąc pod uwagę powyższe zasady, możemy podać przykład zastosowanej semantyki:

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
}

Jeśli chcesz dowiedzieć się więcej o tym mechanizmie, polecam przyjrzeć ToPrimitivesię ToStringoperacjom wewnętrznym i.

Polecam również przeczytanie tego artykułu:


1
Istnieje trzeci „sposób”, jeśli wywołasz this: new String(value)dla dowolnej wartości, zawsze zwróci obiekt typu string.
Herbertusz

@Herbertusz new String({toString: null})rzuca TypeError.
Константин Ван

Dzięki dodaniu symboli String()i + ''teraz mamy dość znaczącą różnicę. String(Symbol())uruchomi się, ale Symbol() + ''zgłosi błąd (a Symbol () przejdzie przez fałszywego strażnika, w przeciwieństwie do wartości null i undefined, więc x && (x + '')może teraz rzucać).
yeerk

24

value.toString()spowoduje błąd, jeśli valuejest null. String(value)nie powinieneś.

Na przykład:

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

nie powiedzie się, ponieważ value == null.

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

powinien wyświetlić komunikat o treści „null” (lub podobny), ale nie ulegnie awarii.


3
Nigdy nie widziałem wyjątku zerowego wskaźnika w javascript ... gdzie to widziałeś?
Dagg Nabbit

miły. byłoby jeszcze ładniej na przykładzie
mykhal

@no, @casablanca Fixed. Jestem przyzwyczajony do Java. @mykhal Jak to wygląda?
Jonathan

Zwraca ciąg „null” :)
moefinley

1

String(value)powinien mieć taki sam wynik jak value.toString()w każdym przypadku, z wyjątkiem wartości bez właściwości, takich jak nulllub undefined. ''+valueprzyniesie ten sam wynik.


1

String () [ wywołanie konstruktora ] w zasadzie wywołuje metodę .toString ()

.toString () i String () można wywołać na wartościach pierwotnych (number, boolean, string) i zasadniczo nie zrobią nic specjalnego:

true => „prawda”

false => „false”

17 => „17”

'hello' => 'hello'

Ale wywoływanie tych funkcji na obiektach jest tam, gdzie robi się interesujące:

jeśli obiekt ma własną funkcję .toString (), zostanie wywołany, gdy kiedykolwiek będziesz potrzebować traktowania tego obiektu jako ciągu (jawnie / niejawnie)

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

Nawiasem mówiąc, jeśli chcesz traktować ten obiekt jako liczbę, powinien on mieć zdefiniowaną funkcję .valueOf () .

co jeśli mamy oba w jednym obiekcie?

jeśli chcemy traktować ten obiekt jako string => użyj .toString ()

jeśli chcemy traktować ten obiekt jako liczbę => użyj .valueOf ()

co jeśli mamy zdefiniowane tylko .valueOf () ?

.valueOf () zdefiniowana wewnątrz obiektu zostanie wywołana niezależnie od tego, czy chcemy obsługiwać obiekt jako ciąg znaków, czy jako liczbę

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.