Przesyłanie do ciągu w JavaScript

184

Znalazłem trzy sposoby na rzutowanie zmiennej Stringw JavaScript.
Szukałem tych trzech opcji w kodzie źródłowym jQuery i wszystkie są w użyciu .
Chciałbym wiedzieć, czy są między nimi jakieś różnice:

value.toString()
String(value)
value + ""

PRÓBNY

Wszystkie wytwarzają tę samą moc wyjściową, ale czy jeden z nich jest lepszy od innych?
Powiedziałbym, że + ""ma tę zaletę, że oszczędza niektóre postacie, ale to nie jest tak duża zaleta, coś jeszcze?

gdoron wspiera Monikę
źródło
1
Wydaje mi się, że jeśli wszystkie rzeczy są równe, standardem toString()byłaby droga.
prawnik
1
@asawyer. A czemu to? Jeśli wszystkie wytwarzają tę samą moc wyjściową i robią to samo, wybierz jedną i idź z nią. Tak sądzę, jeśli tak jest naprawdę .
gdoron wspiera Monikę
1
Dwie pierwsze metody powinny być równoważne (powinieneś sprawdzić standard, ale konstruktor wywoła toString). Trzeci ZWYKLE wytwarza takie same dane wyjściowe, ale wymaga bardzo odmiennego mechanizmu (oprócz prędkości wymaga różnych wywołań, więc może nie być tym, czego oczekujesz dla każdego rodzaju obiektu).
Adriano Repetti
6
Moim zdaniem toStringjest to semantycznie najczystszy sposób na samodzielne udokumentowanie faktu, że próbujesz uzyskać łańcuchowy odpowiednik obiektu. String(...)jest trochę tępy i value + ""jest trochę hack. Daje to również możliwość zastąpienia domyślnej toStringimplementacji niestandardowej, jeśli zajdzie taka potrzeba, jako niewielka dodatkowa korzyść.
prawnik
2
@Adriano. Ale + ""jest najszybszy według jsperf, więc ... robi to w inny sposób, jak sądzę.
gdoron wspiera Monikę

Odpowiedzi:

213

Zachowują się inaczej, gdy valuejest null.

  • null.toString()zgłasza błąd - Nie można wywołać metody „toString” o wartości null
  • String(null)zwraca - „null”
  • null + ""zwraca również - „null”

Bardzo podobne zachowanie ma miejsce, jeśli valuejest undefined(patrz odpowiedź jbabey ).

Poza tym istnieje niewielka różnica w wydajności, o ile nie używasz ich w dużych pętlach, nie warto się martwić.

Connell
źródło
To właściwie interesująca różnica. Dlatego powinieneś powstrzymać się od używania, toString()gdy jeszcze tego nie sprawdziłeś null.
Sammy S.
@SammyS. nie wiem, czy drukowanie nulllub undefinedwyświetlanie na ekranie jest bardziej pożądanym zachowaniem, niż błąd javascript ...
Justus Romijn
@JustusRomijn: Rzeczywiście prawda. W międzyczasie zacząłem używać typu Option do obsługi takich błędów.
Sammy S.
możesz sprawdzić dowolną z tych rzutowanych zmiennych za pomocą typeof, aby sprawdzić ciąg znaków. typeof (null + '') == 'string'
Bruce Lim
4
Jest inny przypadek, gdy zachowują się inaczej. v + ''zwraca niepoprawny wynik, jeśli v ma zarówno metody toString (), jak i valueOf (). Łączenie zignoruje toString () i użyje valueOf (). Przykład klasy, w przypadku której konkatenacja nie powiodła się: github.com/processing-js/processing-js/blob/…
Mikita Belahlazau
26

Istnieją różnice, ale prawdopodobnie nie mają związku z twoim pytaniem. Na przykład prototyp toString nie istnieje na niezdefiniowanych zmiennych, ale można rzutować niezdefiniowany na ciąg, używając dwóch pozostałych metod:

var foo;

var myString1 = String(foo); // "undefined" as a string

var myString2 = foo + ''; // "undefined" as a string

var myString3 = foo.toString(); // throws an exception

http://jsfiddle.net/f8YwA/

jbabey
źródło
3
Jeśli zmienna nie jest w ogóle zdefiniowana, nadal pojawia się błąd dla String(). Przykład: String(test);rzuca Uncaught ReferenceError: test is not defined, a var test; String(test);spowoduje "undefined".
Anthony
17

Zachowują się tak samo, ale toStringzapewniają także konwersję ciągów binarnych, ósemkowych lub szesnastkowych:

Przykład:

var a = (50274).toString(16)  // "c462"
var b = (76).toString(8)      // "114"
var c = (7623).toString(36)   // "5vr"
var d = (100).toString(2)     // "1100100"
Sarfraz
źródło
9

Według tego testu JSPerf różnią się prędkością. Ale chyba, że ​​zamierzasz używać ich w dużych ilościach, każdy z nich powinien działać dobrze.

Dla kompletności: Jak już wspomniano jako prawnik , możesz również użyć tej .toString()metody.

Sammy S.
źródło
2
Że jsperf ma ten sam test dwa razy, edytowałem go I new String()zwraca obiekt, który nie jestString
gdoron obsługuje Monikę
new String()zwraca obiekt tak. String()zwraca jednak ciąg, który jest tym w pytaniu.
Connell,
2
To nie do końca prawda. Jak widać z wyników, konkatenacja pustego łańcucha i obiektu nie daje takiego samego wyniku, jak konkatenacja obiektu i pustego łańcucha. Ponadto new String(blarg)daje ci Stringobiekt, do którego możesz zadzwonić toString(). W moim debuggerze Chrome skutecznie dają ten sam obiekt, z wyjątkiem wspomnianej różnicy.
Sammy S.
@SammyS. Czy możesz dodać przykładowe wyniki działania do swojej odpowiedzi? Link do strony jsperf jest obecnie niedostępny i na pewno pojawi się ponownie w ciągu następnych 5 lat.
mxmlnkn
9

Oprócz wszystkich powyższych należy zauważyć, że dla określonej wartości v:

  • String(v) połączenia v.toString()
  • '' + vpołączenia v.valueOf()przed jakimkolwiek innym typem obsady

Więc możemy zrobić coś takiego:

var mixin = {
  valueOf:  function () { return false },
  toString: function () { return 'true' }
};
mixin === false;  // false
mixin == false;    // true
'' + mixin;       // "false"
String(mixin)     // "true"

Testowane w FF 34.0 i węźle 0.10

Simone C.
źródło
8

jeśli jesteś w porządku z zerami, niezdefiniowanymi, NaN, 0 i false wszystkie rzutowania na „”, to (s ? s+'' : '')jest szybsze.

patrz http://jsperf.com/cast-to-string/8

Uwaga - w tej chwili istnieją znaczne różnice między przeglądarkami.

jldec
źródło
4

Świat realny przykład: Mam funkcję dziennika, który można nazwać z dowolnej liczby parametrów: log("foo is {} and bar is {}", param1, param2). Jeśli DEBUGflaga jest ustawiona na true, nawiasy zastępowane są podanymi parametrami, a ciąg jest przekazywany do console.log(msg). Parametry mogą i będą ciągami, liczbami i czymkolwiek, co może zostać zwrócone przez wywołania JSON / AJAX, a może nawet null.

  • arguments[i].toString()nie jest opcją ze względu na możliwe nullwartości (patrz odpowiedź Connell Watkins)
  • JSLint będzie narzekać arguments[i] + "". To może, ale nie musi, wpływać na decyzję o tym, czego użyć. Niektórzy ludzie ściśle przestrzegają JSLint.
  • W niektórych przeglądarkach łączenie pustych łańcuchów jest nieco szybsze niż użycie funkcji łańcuchowej lub konstruktora łańcuchów (patrz test JSPerf w odpowiedzi Sammys S.). W Operze 12 i Firefox 19 łączenie pustych ciągów jest znacznie szybsze (95% w Firefoksie 19) - a przynajmniej tak twierdzi JSPerf .
Jacek
źródło
1

Na tej stronie możesz samodzielnie przetestować działanie każdej metody :)

http://jsperf.com/cast-to-string/2

tutaj na wszystkich komputerach i przeglądarkach „ ” „+ str ” jest najszybszy, a (String) str jest najwolniejszy

itinance
źródło