Jaki jest najlepszy sposób konwersji liczby na ciąg znaków w JavaScript?

517

Jaki jest „najlepszy” sposób przekonwertowania liczby na ciąg znaków (pod względem przewagi prędkości, przewagi przejrzystości, przewagi pamięci itp.)?

Kilka przykładów:

  1. String(n)

  2. n.toString()

  3. ""+n

  4. n+""

Pacerier
źródło

Odpowiedzi:

516

lubię to:

var foo = 45;
var bar = '' + foo;

W rzeczywistości, chociaż zazwyczaj robię to w ten sposób dla wygody, w przypadku ponad 1000 iteracji wydaje się, że dla prędkości pierwotnej istnieje zaleta dla.toString()

Zobacz testy wydajności tutaj (nie przeze mnie, ale znalazłem, kiedy poszedłem pisać własne): http://jsben.ch/#/ghQYR

Najszybszy na podstawie powyższego testu JSPerf: str = num.toString();

Należy zauważyć, że różnica prędkości nie jest zbyt znacząca, jeśli weźmie się pod uwagę, że można wykonać konwersję w jakikolwiek sposób 1 milion razy w 0,1 sekundy .

Aktualizacja: Szybkość wydaje się znacznie różnić w zależności od przeglądarki. W Chrome num + ''wydaje się być najszybszy na podstawie tego testu http://jsben.ch/#/ghQYR

Aktualizacja 2: Znowu na podstawie mojego powyższego testu należy zauważyć, że Firefox 20.0.1 wykonuje .toString()około 100 razy wolniej niż '' + numpróbka.

scunliffe
źródło
58
Są przypadki, w których konwersja może nie dać preferowanej odpowiedzi: '' + 123e-50zwraca "1.23e-48".
hongymagic
21
@hongymagic: ta odpowiedź jest w rzeczywistości jedyną możliwą do wyobrażenia: liczba nie obchodzi ani nie wie, jak została wprowadzona, a standardowa drukowana reprezentacja ma dokładnie jedną cyfrę przed kropką.
Svante,
4
Uruchomiłem test w jsben.ch/ghQYR , za każdym razem, gdy pokazuje mi inny wynik!
Maryam Saeidi
2
Podoba mi się ta odpowiedź, ponieważ null foonie rzuca błędu.
ttugates
2
@MaryamSaeidi: Korzystanie drublic „s jsperf.com Test powyżej wydaje się bardziej spójna.
Giraldi
364

Moim zdaniem n.toString()bierze nagrodę za wyrazistość i nie sądzę, że wiąże się to z dodatkowymi kosztami.

CarlosZ
źródło
Nosi to pewne obciążenie, mimo że w ostatnich wersjach przeglądarki jest nieznaczne. Przynajmniej w Firefox Quantum
peterchaula,
11
To jest niebezpieczne. n może być zerowy lub niezdefiniowany.
david.pfx
20
@ david.pfx pytanie dotyczy sposobu konwersji wartości liczbowych na ciąg. Dostarczając przykładów wartości nienumerycznych (np null, undefined), które nie działają z tą odpowiedzią prawie sprawia, że „niebezpieczne”.
Michael Martin-Smucker,
5
@ MichaelMartin-Smucker: Jeśli piszesz dużo JS, zdajesz sobie sprawę, że rzeczy rzadko są tak cięte i suszone. Pytanie było otwarte, a IMO dobra odpowiedź powinna przynajmniej potwierdzić kwestię ciągu, który w rzeczywistości jest zerowy lub niezdefiniowany. YMMV.
david.pfx
@ david.pfx Napisałem DUŻO plików js i nie pamiętam, kiedy ostatni raz potrzebowałem liczby jako łańcucha i wystarczyłoby nic oprócz liczby jako łańcucha. To jest poprawna odpowiedź. Nie ma odpowiedzi na obsługę nulllub undefinedponieważ jest ona specyficzna dla aplikacji, podczas gdy wyobrażam sobie, że (n || defaultNumber).toString() jest to, czego większość ludzi chciałaby w takiej sytuacji, zdecydowanie nie zgadzam się, że powinniśmy pracować nad wszystkimi pytaniami. Chodziło o konwersję liczb na ciągi znaków, dobrą architekturę i konwersje innego typu, gdzie potrzebne były osobne lekcje.
George Reith,
73

Jawne konwersje są bardzo jasne dla kogoś, kto nie zna języka. Używanie przymusu typu, jak sugerują inni, prowadzi do niejednoznaczności, jeśli programista nie jest świadomy reguł przymusu. Ostatecznie czas programisty jest droższy niż czas procesora, więc zoptymalizuję ten pierwszy kosztem drugiego. Biorąc to pod uwagę, w tym przypadku różnica jest prawdopodobnie znikoma, ale jeśli nie, jestem pewien, że istnieją pewne przyzwoite kompresory JavaScript, które zoptymalizują tego rodzaju rzeczy.

Z powyższych powodów wybrałbym: n.toString()lub String(n). String(n)jest prawdopodobnie lepszym wyborem, ponieważ nie zawiedzie, jeśli njest pusty lub niezdefiniowany.

Bryan Kyle
źródło
12
Pytanie dotyczyło konwersji liczb, a nie konwersji liczb nulllub undefined. Jeśli njest nulllub z undefinedpowodu błędu w moim programie, wolałbym, aby mój program zawiódł w tym stanie, aby dać mi większą szansę na znalezienie i naprawienie błędu. Awarie programowe są prezentem dla programisty, który pomaga jej znaleźć błędy :-). Alternatywą jest dostarczenie oprogramowania, które nie działa zgodnie z przeznaczeniem, po dokładnym przejrzeniu błędów. Nie jestem fanem String(n)maskowania błędów.
Matt Wallis,
1
String(n)nadaje się do używania w funkcjonalnym stylu, np. z kombajnem podkreślenia _.compose(funcThatNeedsAStringParam, String).
Rik Martins
2
Ciąg (null) nie spowoduje awarii programu, ale zwróci literalny ciąg „null”, co prawdopodobnie nie jest tym, czego chcesz. Jeśli dane mogą być zgodne z prawem, to należy je traktować jawnie.
Peter Smartt
1
@MattWallis Myślę, że to powinna być decyzja dewelopera, a nie odpowiedzi, nie sądzisz?
forresthopkinsa
30

... Parser JavaScript próbuje przeanalizować notację kropkową na liczbie jako literał zmiennoprzecinkowy.

2..toString(); // the second point is correctly recognized
2 .toString(); // note the space left to the dot
(2).toString(); // 2 is evaluated first

Źródło

Mohammad Arif
źródło
17

Zuchwały język oczywiście:

var harshNum = 108;
"".split.call(harshNum,"").join("");

Lub w ES6 możesz po prostu użyć ciągów szablonów :

var harshNum = 108;
`${harshNum}`;
cssimsek
źródło
Jeśli uruchamiam testy porównawcze z szablonami ES6, czasem okazuje się nawet, że są szybsze niż '' + numbermetoda. To powiedziawszy, wyniki tych testów porównawczych bardzo się różnią podczas ich wielokrotnego wykonywania, więc nie jestem pewien, czy należy je traktować zbyt poważnie.
Nico Van Belle,
15

Inne odpowiedzi już dotyczyły innych opcji, ale wolę tę:

s = `${n}`

Krótkie, zwięzłe, używane już w wielu innych miejscach (jeśli używasz nowoczesnej wersji framework / ES), więc jest to bezpieczny zakład, że każdy programista to zrozumie.

Nie znaczy to, że (zwykle) ma to duże znaczenie, ale wydaje się również, że należy do najszybszych w porównaniu do innych metod .

johndodo
źródło
Jest również bezpieczne, jeśli n może nie być liczbą.
david.pfx
Ale tak jest n.toString(), prawda?
AMN
1
@amn jeśli nto undefinedbędzie rzucać błąd składni przy użyciu.toString()
Jee mok
Czy to nie daje takiego samego rezultatu jak String(n)we wszystkich przypadkach? Jedyną różnicą jest to, że jest mniej jasne.
Bennett McElwee
I znacznie wolniej.
Adrian Bartholomew
12

Najprostszym sposobem na konwersję dowolnej zmiennej na ciąg jest dodanie pustego ciągu do tej zmiennej.

5.41 + ''    // Result: the string '5.41'
Math.PI + '' // Result: the string '3.141592653589793'
sgokhales
źródło
2
Należy pamiętać, że musi on znajdować się wewnątrz parens: (5.41 + '')aby używać metod String, takich jak .substring()i innych
Gjaa,
Dlaczego należy to zauważyć?
Adrian Bartholomew
7

Jeśli chcesz sformatować wynik do określonej liczby miejsc po przecinku, na przykład w celu przedstawienia waluty, potrzebujesz czegoś takiego jak toFixed()metoda.

number.toFixed( [digits] )

digits to liczba cyfr wyświetlanych po przecinku.

Tim
źródło
2
Niebezpieczne, chyba że wiesz, że to liczba.
david.pfx
6

Użyłem https://jsperf.com, aby utworzyć przypadek testowy dla następujących przypadków:

number + ''
`${number}`
String(number)
number.toString()

https://jsperf.com/number-string-conversion-speed-comparison

Według stanu na 24 lipca 2018 r. Wyniki wskazują, że number + ''jest to najszybszy w Chrome, w Firefox, który łączy się z literałami ciągów szablonów.

Obaj String(number), i number.toString()wynosi około 95% wolniej niż najszybszy opcji.

testy wydajności, opis powyżej

Erick
źródło
2

Lubię dwa pierwsze, ponieważ są łatwiejsze do odczytania. Zwykle używam, String(n)ale to tylko kwestia stylu niż cokolwiek innego.

To znaczy, chyba że masz linię jak

var n = 5;
console.log ("the number is: " + n);

co jest bardzo oczywiste

Aleadam
źródło
2

Myślę, że to zależy od sytuacji, ale i tak możesz użyć tej .toString()metody, ponieważ jest to bardzo jasne do zrozumienia.

Serghei
źródło
2

.toString () to wbudowana funkcja rzutowania czcionek, nie jestem ekspertem w tych szczegółach, ale ilekroć porównujemy wbudowane metody rzutowania wierszy, zawsze preferowane są wbudowane obejścia.

Mubeen Khan
źródło
1

Gdybym musiał wziąć wszystko pod uwagę, zasugeruję następujące

var myint = 1;
var mystring = myint + '';
/*or int to string*/
myint = myint + ''

IMHO, to najszybszy sposób na konwersję na ciąg. Popraw mnie, jeśli się mylę.

Kumar
źródło
1

Jedynym prawidłowym rozwiązaniem dla prawie wszystkich możliwych istniejących i przyszłych przypadków (wejście to liczba, null, niezdefiniowany, symbol, cokolwiek innego) to String(x). Nie używaj 3 sposobów prostej operacji, w oparciu o założenia typu wartości, np. „Tutaj zdecydowanie przekonwertowałem liczbę na ciąg znaków, a tutaj zdecydowanie boolean na ciąg znaków”.

Wyjaśnienie:

String(x)obsługuje wartości zerowe, niezdefiniowane, symbole, [cokolwiek] i wywołuje .toString()obiekty.

'' + xwywołuje .valueOf()x (rzut na numer), rzuca symbole, może zapewnić wyniki zależne od implementacji.

x.toString() rzuca na wartości zerowe i niezdefiniowane.

Uwaga: String(x)nadal zawiedzie na obiektach bez prototypów, takich jak Object.create(null).

Jeśli nie lubisz ciągów takich jak „Hello, undefined” lub chcesz obsługiwać obiekty bez prototypów, użyj następującej funkcji konwersji typu:

/**
 * Safely casts any value to string. Null and undefined are converted to ''.
 * @param  {*} value
 * @return {string}
 */
function string (str) {
  return value == null ? '' : (typeof value === 'object' && !value.toString ? '[object]' : String(value));
}
Alexander Shostak
źródło
1

W przypadku literałów liczbowych kropka dostępu do właściwości musi być odróżniona od kropki dziesiętnej. To pozostawia Ci następujące opcje, jeśli chcesz wywołać String () na literał liczbowy 123:

123..toString()
123 .toString() // space before the dot 123.0.toString()
(123).toString()
Mohit Dabas
źródło
1

Poniżej znajdują się metody konwersji liczby całkowitej na ciąg w JS

Metody są ułożone w kolejności malejącej wydajności.

(Wyniki testu wydajności podane przez @DarckBlezzer w swojej odpowiedzi)

var num = 1

Metoda 1:

num = `$ {num}`

Metoda 2:

num = num + ''

Metoda 3:

num = ciąg (num)

Metoda 4:

num = num.toString ()

Uwaga: Nie można bezpośrednio wywoływać funkcji tostring () z numeru

Np .: 2.toString () wyrzuci Uncaught SyntaxError : Niepoprawny lub nieoczekiwany token

Arun Joshla
źródło
0

Jeśli jesteś ciekawy, która z nich jest najbardziej wydajna, sprawdź to, gdzie porównuję wszystkie różne konwersje Number -> String.

Wygląda 2+''lub 2+""jest najszybszy.

https://jsperf.com/int-2-string

Alex Cory
źródło
0

Możemy również użyć konstruktora String . Według tego testu porównawczego jest to najszybszy sposób konwersji liczby na ciąg znaków w przeglądarce Firefox 58, nawet jeśli jest wolniejszy niż " + numw popularnej przeglądarce Google Chrome.

peterchaula
źródło
0

Metoda toFixed()rozwiąże również cel.

var n = 8.434332;
n.toFixed(2)  // 8.43
Shaik Rasool
źródło
0

Możesz wywołać Numberobiekt, a następnie zadzwonić toString().

Number.call(null, n).toString()

Możesz użyć tej sztuczki do innych rodzimych obiektów javascript.

ufadiz
źródło
0

Po prostu natknęliśmy się na to niedawno, metody 3 i 4 nie są odpowiednie, ponieważ w jaki sposób ciągi są kopiowane, a następnie łączone. W przypadku małego programu problem ten jest nieznaczny, ale w przypadku każdej prawdziwej aplikacji internetowej działanie, w którym mamy do czynienia z manipulacjami ciągami częstotliwości, może wpłynąć na wydajność i czytelność.

Oto link do przeczytania .

zrozumiałem
źródło
0

Mam zamiar ponownie to edytować, dodając więcej danych, kiedy będę miał na to czas, bo w tej chwili jest w porządku ...

Test w nodejs v8.11.2: 2018/06/06

let i=0;
    console.time("test1")
    for(;i<10000000;i=i+1){
    	const string = "" + 1234;
    }
    console.timeEnd("test1")
    
    i=0;
    console.time("test1.1")
    for(;i<10000000;i=i+1){
    	const string = '' + 1234;
    }
    console.timeEnd("test1.1")
    
    i=0;
    console.time("test1.2")
    for(;i<10000000;i=i+1){
    	const string = `` + 1234;
    }
    console.timeEnd("test1.2")
    
    i=0;
    console.time("test1.3")
    for(;i<10000000;i=i+1){
    	const string = 1234 +  '';
    }
    console.timeEnd("test1.3")
    
    
    i=0;
    console.time("test2")
    for(;i<10000000;i=i+1){
    	const string = (1234).toString();
    }
    console.timeEnd("test2")
    
    
    i=0;
    console.time("test3")
    for(;i<10000000;i=i+1){
    	const string = String(1234);
    }
    console.timeEnd("test3")
    
    
    i=0;
    console.time("test4")
    for(;i<10000000;i=i+1){
    	const string = `${1234}`;
    }
    console.timeEnd("test4")
    
    i=0;
    console.time("test5")
    for(;i<10000000;i=i+1){
    	const string = 1234..toString();
    }
    console.timeEnd("test5")
    
    i=0;
    console.time("test6")
    for(;i<10000000;i=i+1){
    	const string = 1234 .toString();
    }
    console.timeEnd("test6")

wynik

test1: 72.268ms
test1.1: 61.086ms
test1.2: 66.854ms
test1.3: 63.698ms
test2: 207.912ms
test3: 81.987ms
test4: 59.752ms
test5: 213.136ms
test6: 204.869ms
DarckBlezzer
źródło
Tak - regularnie używam test4 !!
Adrian Bartłomiej
0

Wydaje się, że wyniki są podobne w przypadku używania node.js. Uruchomiłem ten skrypt:

let bar;
let foo = ["45","foo"];

console.time('string concat testing');
for (let i = 0; i < 10000000; i++) {
    bar = "" + foo;
}
console.timeEnd('string concat testing');


console.time("string obj testing");
for (let i = 0; i < 10000000; i++) {
    bar = String(foo);
}
console.timeEnd("string obj testing");

console.time("string both");
for (let i = 0; i < 10000000; i++) {
    bar = "" + foo + "";
}
console.timeEnd("string both");

i uzyskał następujące wyniki:

 node testing.js
string concat testing: 2802.542ms
string obj testing: 3374.530ms
string both: 2660.023ms

Podobne razy za każdym razem, gdy go uruchomiłem.

Shahaed
źródło