Jak zrobić pierwszą literę wielkiej litery w JavaScript?


3757

Jak zrobić pierwszą literę ciągu wielkimi literami, ale nie zmieniać wielkości liter w pozostałych literach?

Na przykład:

  • "this is a test" -> "This is a test"
  • "the Eiffel Tower" -> "The Eiffel Tower"
  • "/index.html" -> "/index.html"

12
Underscore ma wtyczkę o nazwie underscore.string, która zawiera to i kilka innych świetnych narzędzi.
Aaron

co z:return str.replace(/(\b\w)/gi,function(m){return m.toUpperCase();});
Muhammad Umer

110
Prostsze:string[0].toUpperCase() + string.substring(1)
dr.dimitru

6
`${s[0].toUpperCase()}${s.slice(1)}`
noego

([initial, ...rest]) => [initial.toUpperCase(), ...rest].join("")
Константин Ван

Odpowiedzi:


5804

Podstawowym rozwiązaniem jest:

function capitalizeFirstLetter(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

console.log(capitalizeFirstLetter('foo')); // Foo

Niektóre inne odpowiedzi zmieniają się String.prototype(ta odpowiedź również kiedyś), ale odradzałbym to teraz ze względu na łatwość konserwacji (trudny do ustalenia, gdzie funkcja jest dodawana do prototypei może powodować konflikty, jeśli inny kod używa tej samej nazwy / przeglądarki) dodaje funkcję natywną o tej samej nazwie w przyszłości).

... a potem, gdy rozważasz internacjonalizację, jest o wiele więcej, o czym świadczy ta zadziwiająco dobra odpowiedź (ukryta poniżej).

Jeśli chcesz pracować z punktami kodowymi Unicode zamiast z jednostkami kodowymi (na przykład, aby obsługiwać znaki Unicode poza Podstawową płaszczyzną wielojęzyczną), możesz wykorzystać fakt, że String#[@iterator]działa on z punktami kodowymi, i możesz użyć, toLocaleUpperCaseaby uzyskać poprawne ustawienia regionalne:

function capitalizeFirstLetter([ first, ...rest ], locale = navigator.language) {
  return [ first.toLocaleUpperCase(locale), ...rest ].join('');
}

console.log(capitalizeFirstLetter('foo')); // Foo
console.log(capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉")); // "𐐎𐐲𐑌𐐼𐐲𐑉" (correct!)
console.log(capitalizeFirstLetter("italya", 'tr')); // İtalya" (correct in Turkish Latin!)

Aby uzyskać jeszcze więcej opcji internacjonalizacji, zobacz oryginalną odpowiedź poniżej .


9
substring jest rozumiany w większej liczbie przeglądarek niż substr
mplungjan

6
dodać do karim79 - prawdopodobnie przesada, aby uczynić go funkcją, ponieważ javascript zrobi to samo ze zmienną bez zawijania funkcji. Przypuszczam, że użycie funkcji byłoby bardziej zrozumiałe, ale w przeciwnym razie jej natywny, po co komplikować ją za pomocą opakowania funkcji?
Ross

18
Czy nie powinniśmy również obniżyć liczby (1)?
hasen

177
Nie, ponieważ PO dał ten przykład: the Eiffel Tower -> The Eiffel Tower. Dodatkowo funkcja nazywa się „ capitaliseFirstLetternie” capitaliseFirstLetterAndLowerCaseAllTheOthers.
zakaz geoinżynierii

22
Nikt nie dba o ważną zasadę OOP? - Nigdy nie edytuj obiektów, których nie posiadasz? . BTW, ta string[0].toUpperCase() + string.substring(1)
jednowarstwowa

1349

Oto podejście bardziej obiektowe:

String.prototype.capitalize = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

Wywołalibyśmy tę funkcję w następujący sposób:

"hello world".capitalize();

Oczekiwany wynik to:

"Hello world" 

24
Podoba mi się to rozwiązanie, ponieważ jest jak Ruby, a Ruby jest słodka! :) return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
Małe

164
W tym świecie po Prototype.js nie zaleca się zmiany ani rozszerzenia obiektów macierzystych.
Ryan,

191
@rxgx - Boogeyman „nie przedłużaj” zaczyna wymierać (dzięki Bogu), a ludzie wyciągają głowy z jSand i zdają sobie sprawę, że to tylko funkcja językowa. Tylko dlatego, że Prototype.js rozszerzył sam obiekt przez krótki czas, nie oznacza, że ​​rozszerzanie tubylców jest złe. Nie powinieneś tego robić, jeśli piszesz kod dla nieznanego konsumenta (np. Skrypt analityczny, który trafia na losowe strony), ale poza tym jest w porządku.
csuwldcat

43
@csuwldcat Co zrobić, jeśli inna biblioteka, której używasz, dodaje swoją wielką literę, nie wiedząc o tym? Rozszerzanie prototypów jest złą formą, niezależnie od tego, czy Prototype.js to zrobiło czy nie. Dzięki ES6 intrinsics pozwoli Ci zjeść ciasto i zjeść je. Myślę, że możesz pomylić „boogeyman” wymierający dla ludzi tworzących podkładki, które są zgodne ze specyfikacją ECMASCRIPT. Te podkładki są idealnie w porządku, ponieważ inna biblioteka, która dodała podkładkę, zaimplementowałaby ją w ten sam sposób. Należy jednak unikać dodawania własnych niespecyficznych elementów wewnętrznych.
Justin Meyer,

43
Przedłużanie tubylców jest BARDZO złą praktyką. Nawet jeśli powiesz „och, nigdy nie będę używać tego kodu z niczym innym”, prawdopodobnie ty (lub ktoś inny) to zrobisz. Potem spędzą trzy dni próbując znaleźć jakiś dziwny błąd matematyczny, ponieważ ktoś rozszerzył Number.money (), aby zająć się walutą nieco inną niż twoja inna biblioteka. Poważnie, widziałem, jak to się dzieje w dużej firmie i nie warto poświęcać czasu na debugowanie, aby znaleźć bibliotekę opracowaną przez prototypy tubylców.
phreakhead

573

W CSS:

p:first-letter {
    text-transform:capitalize;
}

80
OP prosi o rozwiązanie JS.
Antonio Max

129
$ ('# mystring_id'). text (string) .css ('text-transform', 'capitalize');
DonMB

21
Dodatkowo wpływa to tylko na wyświetlanie ciągu - nie na rzeczywistą wartość. Jeśli jest w formie, np. Wartość będzie nadal przesyłana w niezmienionej postaci.
dmansfield

12
Ta odpowiedź pomogła mi uświadomić sobie, że rozwiązanie CSS naprawdę bardziej pasuje do tego, co robię. @dudewad: Odpowiedź prawdopodobnie powinna dać zastrzeżenie, że nie jest to rozwiązanie JS, ale może być bardziej odpowiednie w zależności od potrzeby.
joshden

58
Dla około 80% widzów odwiedzających to pytanie będzie to najlepsza odpowiedź. Nie odpowiedź na pytanie , ale na problem .
Jivan

290

Oto skrócona wersja popularnej odpowiedzi, która otrzymuje pierwszą literę, traktując ciąg znaków jako tablicę:

function capitalize(s)
{
    return s[0].toUpperCase() + s.slice(1);
}

Aktualizacja:

Zgodnie z poniższymi komentarzami nie działa to w IE 7 lub niższej.

Aktualizacja 2:

Aby uniknąć undefinedpustych łańcuchów (patrz komentarz @ njzk2 poniżej ), możesz sprawdzić, czy łańcuch jest pusty:

function capitalize(s)
{
    return s && s[0].toUpperCase() + s.slice(1);
}

23
To nie będzie działać w IE <8, ponieważ te przeglądarki nie obsługują indeksowania ciągów. IE8 sam to obsługuje, ale tylko dla literałów łańcuchowych - nie dla obiektów łańcuchowych.
Mathias Bynens

52
kogo to obchodzi, rynek IE7 jest mniej niż 5%! i są to prawdopodobnie stare maszyny twojego gremmy i grempy. Mówię krótki kod FTW!
vsync

@MathiasBynens Czy wiesz, czy dotyczy to starszych przeglądarek innych niż IE, czy tylko IE7? Jeśli indeksowanie literałów łańcuchowych w 2014 r. Nie dotyczy innych przeglądarek, wszystko powinno być w porządku. :)
hexalys

3
@vsync Chodziło mi po prostu o to, że w zależności od danych demograficznych użytkowników, czasami (choć z wdzięcznością coraz mniej, gdy mijamy 2014 r. i później) opłaca się obsługiwać stare przeglądarki, takie jak IE7 ...
joshuahedlund

2
@ njzk2, aby obsłużyć pusty ciąg, możesz zaktualizować do tego: return s && s[0].toUpperCase() + s.slice(1);
joelvh

188

Jeśli jesteś zainteresowany wydajnością kilku różnych opublikowanych metod:

Oto najszybsze metody oparte na tym teście jsperf (uporządkowane od najszybszego do najwolniejszego).

Jak widać, pierwsze dwie metody są zasadniczo porównywalne pod względem wydajności, podczas gdy zmiana String.prototypejest zdecydowanie najwolniejsza pod względem wydajności.

// 10,889,187 operations/sec
function capitalizeFirstLetter(string) {
    return string[0].toUpperCase() + string.slice(1);
}

// 10,875,535 operations/sec
function capitalizeFirstLetter(string) {
    return string.charAt(0).toUpperCase() + string.slice(1);
}

// 4,632,536 operations/sec
function capitalizeFirstLetter(string) {
    return string.replace(/^./, string[0].toUpperCase());
}

// 1,977,828 operations/sec
String.prototype.capitalizeFirstLetter = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

wprowadź opis zdjęcia tutaj


1
Wygląda na to, że kod inicjalizacji również nie ma znaczenia: jsperf.com/capitalize-first-letter-of-string/2
user420667

6
Należy również pamiętać, że zastąpienie .slice(1)go .substr(1)jeszcze bardziej zwiększy wydajność.
Przemek

2
Rozsądna uwaga. Pamiętaj jednak, że w wielu przypadkach wydajność nie jest nawet zauważalna: nawet „najwolniejsze” podejście poradziłoby sobie z 19 000 ciągów w 10 ms. Wybierz więc najbardziej wygodny dla siebie.
Cytując Eddiego

1
W przypadku, gdy ktoś jest ciekawy (jak ja), jak wzrosła jego wydajność w ciągu ostatnich czterech lat, liczba operacji na sekundę w trzeciej wersji MacBooka Pro 2018 wynosi 135 307 869, a więc jest 12,4 razy szybsza.
Carlo Field

151

W innym przypadku potrzebuję go, aby pierwsza litera była wielką literą, a pozostałe małe. Następujące przypadki zmusiły mnie do zmiany tej funkcji:

//es5
function capitalize(string) {
    return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
}
capitalize("alfredo")  // => "Alfredo"
capitalize("Alejandro")// => "Alejandro
capitalize("ALBERTO")  // => "Alberto"
capitalize("ArMaNdO")  // => "Armando"

// es6 using destructuring 
const capitalize = ([first,...rest]) => first.toUpperCase() + rest.join('').toLowerCase();

1
„... ale nie zmieniaj wielkości liter innych liter”. To nie jest poprawna odpowiedź na pytanie zadane przez PO.
Carlos Muñoz

2
@ CarlosMuñoz, jeśli czytasz zdanie wstępne, mówi, że dotyczy to innego przypadku.
TMH

3
@TomHart Właśnie dlatego nie jest to rozwiązanie pytania. Powinien to być komentarz lub inne pytanie i odpowiedź
Carlos Muñoz

15
Zgadzam się z tobą w tej sprawie, ale widzę, że wiele osób kończy tutaj, szukając odpowiedzi na to pytanie.
TMH

74

Oto rozwiązanie ECMAScript 6+ 2018 :

const str = 'the Eiffel Tower';
const newStr = `${str[0].toUpperCase()}${str.slice(1)}`;
console.log('Original String:', str); // the Eiffel Tower
console.log('New String:', newStr); // The Eiffel Tower


5
.slice()jest wolniejszy niż .substring(), str[0]byłby undefinedto pusty ciąg i użycie literałów szablonów do połączenia dwóch części wprowadza tutaj 8 znaków, a +wprowadziłby tylko 3.
Przemek

4
Celem mojej odpowiedzi Prz jest prezentacja nowych funkcji obsługiwanych przez ES6, w szczególności literałów szablonów, o których nie wspomniano w innych postach. Idea StackOverflow polega na udostępnieniu wyszukiwarce „opcji”. Mogą wziąć opis literałów szablonów opisanych w tej odpowiedzi i połączyć je z ulepszeniami mikro prędkości, takimi jak Substring v. Plaster, jeśli ich zastosowanie wymaga dodatkowych zaoszczędzonych milisekund. Moja odpowiedź nie obejmuje również testów jednostkowych, co pokazuje, że nigdy nie należy kopiować bezpośrednio odpowiedzi StackOverflow. Zakładam, że programista weźmie moją odpowiedź i dostosuje ją.
Sterling Bourne

Nic nie zyskujesz dzięki zastosowaniu literałów szablonów tutaj, a po ${}prostu dodaje hałasu. const newStr = str[0].toUpperCase() + str.slice(1);jest łatwiejszy do odczytania.
Boris

1
Zgadzam się nie zgadzać co do tego, co jest łatwiejsze do odczytania.
Sterling Bourne,

67

Jeśli już korzystasz (lub rozważasz) lodash, rozwiązanie jest proste:

_.upperFirst('fred');
// => 'Fred'

_.upperFirst('FRED');
// => 'FRED'

_.capitalize('fred') //=> 'Fred'

Zobacz ich dokumenty: https://lodash.com/docs#capitalize

_.camelCase('Foo Bar'); //=> 'fooBar'

https://lodash.com/docs/4.15.0#camelCase

_.lowerFirst('Fred');
// => 'fred'

_.lowerFirst('FRED');
// => 'fRED'

_.snakeCase('Foo Bar');
// => 'foo_bar'

Vanilla js na pierwszą wielką literę:

function upperCaseFirst(str){
    return str.charAt(0).toUpperCase() + str.substring(1);
}

11
Myślę, że preferowane powinny być waniliowe Js, ponieważ większość ludzi nie pobierze całego frameworka tylko po to, aby napisać wielką literą.
GGG,

7
Do tej pory we wszystkich moich projektach nigdy nie korzystałem z lodash. Nie zapominaj też, że większość osób w Google skończy na tej stronie, a umieszczenie frameworka jako alternatywy jest w porządku, ale nie jako główna odpowiedź.
GGG,

2
Ponieważ inne odpowiedzi używają waniliowej js, miło jest mieć taką odpowiedź, ponieważ wielu z nas używa lodash / podkreślenia.
Lu Roman

1
To nie jest poprawna odpowiedź, ponieważ OP prosi o zrobienie tego teraz w Javascript, a nie w Javascript, która importuje całą bibliotekę jako zależność od twojego projektu. Nie używaj tego.
dudewad

1
Pytanie OP jest waniliowe na końcu mojej odpowiedzi.
chovy

62

Wielką literą wszystkich słów w ciągu powinna być wielka litera:

function ucFirstAllWords( str )
{
    var pieces = str.split(" ");
    for ( var i = 0; i < pieces.length; i++ )
    {
        var j = pieces[i].charAt(0).toUpperCase();
        pieces[i] = j + pieces[i].substr(1);
    }
    return pieces.join(" ");
}

14
Ponownie przeczytaj pytanie: Chcę zapisać wielką literę pierwszego ciągu, ale nie zmieniaj wielkości liter w pozostałych literach.
JimmyPena

2
Wiem, że tak. Dodałbym jedną rzecz, na wypadek gdyby cały łańcuch zaczynał się wielkimi literami: pieces [i] = j + pieces [i] .substr (1) .toLowerCase ();
Malovich,

4
Inne rozwiązanie tego przypadku: funkcja capitaliseFirstLetters (s) {return s.split ("") .map (function (w) {return w.charAt (0) .toUpperCase () + w.substr (1)}). („”)} Może być ładnym jednowierszowym, jeśli nie jest włączony w funkcję.
Luke Channings

Lepiej byłoby najpierw napisać małymi literami cały ciąg
Magico,

Poza tą funkcją, która nie odpowiada na pytanie, w rzeczywistości jest również nadmiernie skomplikowana. s => s.split(' ').map(x => x[0].toUpperCase() + x.slice(1)).join(' ')
OverCoder

48

Możemy dostać pierwszą postać z jedną z moich ulubionych RegExp, wygląda jak słodka buźka:/^./

String.prototype.capitalize = function () {
  return this.replace(/^./, function (match) {
    return match.toUpperCase();
  });
};

I dla wszystkich ćpunów kawy:

String::capitalize = ->
  @replace /^./, (match) ->
    match.toUpperCase()

... i dla wszystkich facetów, którzy myślą, że jest lepszy sposób na to, bez rozszerzania natywnych prototypów:

var capitalize = function (input) {
  return input.replace(/^./, function (match) {
    return match.toUpperCase();
  });
};

2
Jest lepszy sposób na zrobienie tego bez modyfikowania prototypu String.
Big McLargeHuge

2
@ davidkennedy85 Pewnie! Ale to prosty, a nie najlepszy sposób ... ;-)
yckart

Drogi panienku, na to pytanie jest milion odpowiedzi! Twoje rozwiązanie wygląda jeszcze ładniej w es6. 'Answer'.replace(/^./, v => v.toLowerCase())
stwilz


45

Jeśli używasz underscore.js lub Lo-Dash , biblioteka underscore.string zapewnia rozszerzenia ciągów, w tym wielkie litery:

_.capitalize (string) Konwertuje pierwszą literę ciągu na wielkie litery.

Przykład:

_.capitalize("foo bar") == "Foo bar"

3
Od wersji 3.0.0 Lo-Dash ma domyślnie tę metodę ciągu. Tak jak to opisano w tej odpowiedzi: _.capitalize("foo") === "Foo".
bardzusny

Istnieją również przydatne funkcje o nazwie underscore.js humanize. Przekształca podkreśloną, wielbłądzią lub przerywaną strunę w humanizowaną. Usuwa również początkowe i końcowe białe znaki oraz usuwa postfiks „_id”.
Stepan Zacharow

1
Od wersji 4 * Lodash także małe litery () co drugą literę, bądź ostrożny!
Igor Loskutov

45
String.prototype.capitalize = function(allWords) {
   return (allWords) ? // if all words
      this.split(' ').map(word => word.capitalize()).join(' ') : //break down phrase to words then  recursive calls until capitalizing all words
      this.charAt(0).toUpperCase() + this.slice(1); // if allWords is undefined , capitalize only the first word , mean the first char of the whole string
}

I wtedy:

 "capitalize just the first word".capitalize(); ==> "Capitalize just the first word"
 "capitalize all words".capitalize(true); ==> "Capitalize All Words"

Zaktualizuj listopad 2016 (ES6), tylko dla ZABAWY:

const capitalize = (string = '') => [...string].map(    //convert to array with each item is a char of string by using spread operator (...)
    (char, index) => index ? char : char.toUpperCase()  // index true means not equal 0 , so (!index) is the first char which is capitalized by `toUpperCase()` method
 ).join('')                                             //return back to string

następnie capitalize("hello") // Hello


3
Myślę, że jest to kiepskie rozwiązanie z dwóch powodów: Modyfikacja prototypu prymitywnego jest złym pomysłem. Jeśli specyfikacja ulegnie zmianie i zdecydują się wybrać „wielkie litery” jako nową nazwę właściwości proto, łamiesz podstawową funkcjonalność języka. Ponadto wybrana nazwa metody jest niska. Na pierwszy rzut oka, pomyślałbym, że to skapitalizuje cały łańcuch. Użycie bardziej opisowej nazwy, takiej jak ucFirst PHP lub coś podobnego, może być lepszym pomysłem.
dudewad

Drugi ES6 odpowiedź jest prostsza: const capitalize = ([first,...rest]) => first.toUpperCase() + rest.join('').toLowerCase();.
Dan Dascalescu

44

NAJKRÓTSZA 3 rozwiązania, 1 i 2 przypadki, gdy uchwyt sciąg jest "", nulli undefined:

 s&&s[0].toUpperCase()+s.slice(1)        // 32 char

 s&&s.replace(/./,s[0].toUpperCase())    // 36 char - using regexp

'foo'.replace(/./,x=>x.toUpperCase())    // 31 char - direct on string, ES6


42

Tylko CSS

p::first-letter {
  text-transform: uppercase;
}
  • Pomimo wywołania ::first-letter, odnosi się do pierwszego znaku , tj. W przypadku łańcucha %a, ten selektor miałby zastosowanie do %i jako taki anie byłby pisany wielkimi literami.
  • W IE9 + lub IE5.5 + jest obsługiwany w zapisie starszej wersji tylko z jednym dwukropkiem ( :first-letter).

ES2015 z jedną wkładką

Ponieważ istnieje wiele odpowiedzi, ale w ES2015 nie ma takich, które mogłyby skutecznie rozwiązać pierwotny problem, wymyśliłem:

const capitalizeFirstChar = str => str.charAt(0).toUpperCase() + str.substring(1);

Uwagi

  • parameters => functionjest tak zwaną funkcją strzałki .
  • Poszedłem z imieniem capitalizeFirstCharzamiast capitalizeFirstLetter, ponieważ OP nie poprosił o kod, który zapisuje wielką literę w całym ciągu, ale pierwszy znak (jeśli oczywiście jest to litera).
  • const daje nam możliwość deklaracji capitalizeFirstChar jako stałej, co jest pożądane, ponieważ jako programista zawsze powinieneś wyraźnie określać swoje zamiary.
  • W przeprowadzonym przeze mnie teście porównawczym nie było znaczącej różnicy między string.charAt(0)i string[0]. Zauważ jednak, że string[0]byłby to undefinedpusty ciąg, więc należy go przepisać na string && string[0], co jest zbyt szczegółowe, w porównaniu do alternatywy.
  • string.substring(1)jest szybszy niż string.slice(1).

Reper

  • 4 956 962 operacji / s ± 3,03% dla tego rozwiązania,
  • 4,577,946 operacji / s ± 1,2% dla najczęściej głosowanych odpowiedzi.
  • Utworzono za pomocą JSBench.me w Google Chrome 57.

Porównanie rozwiązań


@Zielony: tak , czy na pewno wybrałeś selektor dwoma dwukropkami?
Przemek

1
W rzeczywistości nie chcesz używać znaku plus (+) jako metody konkatenacji w ES6. Będziesz chciał użyć literałów szablonów: eslint.org/docs/rules/prefer-template
Sterling Bourne

42

Istnieje bardzo prosty sposób na wdrożenie go przez zastąpienie . W przypadku ECMAScript 6:

'foo'.replace(/^./, str => str.toUpperCase())

Wynik:

'Foo'

1
Jak dotąd najlepsza odpowiedź i dodatkowe punkty za pokazanie wyrażenia regularnego lambda. Szczególnie podoba mi się ten, ponieważ może być płynnie wycinany i wklejany w dowolnym miejscu.
Wade Hatler

Używanie /^[a-z]/ibędzie lepsze niż używanie .jako poprzednie, ponieważ nie będzie próbował zastąpić żadnego znaku innego niż alfabet
Code Maniac

38

W CSS wydaje się to łatwiejsze:

<style type="text/css">
    p.capitalize {text-transform:capitalize;}
</style>
<p class="capitalize">This is some text.</p>

Pochodzi z CSS Text-Transform Property (w W3Schools ).


28
@ Simon Nie jest powiedziane, że ciąg musi być wyprowadzany jako część dokumentu HTML - CSS będzie użyteczny tylko wtedy, gdy jest.
Adam Hepton

9
Adam, prawda, ale zgaduję, że ponad 95% dostępnych Javascript jest używanych w HTML i CSS. Niestety, polecenie „wielkie litery” w rzeczywistości zawiera wielkie litery każdego słowa , więc JS nadal potrzebuje dużej litery tylko do pierwszej litery.
Simon East

18
Niepoprawnie, Dinesh. Powiedział pierwszy znak sznurka .
Simon East

81
Ta odpowiedź, mimo że ma absurdalną liczbę głosów pozytywnych, jest po prostu błędna, ponieważ zawiera pierwszą literę każdego słowa. @ Ryan, otrzymasz odznakę dyscyplinarną, jeśli ją usuniesz. Zrób tak, proszę.
Dan Dascalescu,

10
Zgadzam się z @DanDascalescu - odpowiedź Ryana jest całkowicie błędna.
Timo

38
var capitalized = yourstring[0].toUpperCase() + yourstring.substr(1);

38

Nie widziałem żadnej wzmianki w istniejących odpowiedziach na problemy związane z punktami kodu samolotu astralnego lub internacjonalizacją. „Wielkie litery” nie oznaczają tego samego w każdym języku używającym danego skryptu.

Początkowo nie widziałem żadnych odpowiedzi dotyczących problemów związanych z punktami kodu płaszczyzny astralnej. Jest jeden , ale jest trochę pochowany (tak chyba będzie!)


Większość proponowanych funkcji wygląda następująco:

function capitalizeFirstLetter(str) {
  return str[0].toUpperCase() + str.slice(1);
}

Jednak niektóre znaki z literami nie mieszczą się w BMP (podstawowa płaszczyzna wielojęzyczna, punkty kodowe U + 0 do U + FFFF). Weźmy na przykład następujący tekst:

capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉"); // "𐐶𐐲𐑌𐐼𐐲𐑉"

Pierwszy znak tutaj nie używa wielkich liter, ponieważ indeksowane przez tablicę właściwości ciągów nie mają dostępu do „znaków” ani punktów kodowych *. Dostęp do jednostek kodu UTF-16. Dotyczy to również krojenia - wartości indeksu wskazują jednostki kodu.

Zdarza się, że jednostki kodu UTF-16 to 1: 1 z punktami kodowymi USV w dwóch zakresach, od U + 0 do U + D7FF i U + E000 do U + FFFF włącznie. Większość znaków w skrzynkach należy do tych dwóch zakresów, ale nie wszystkie.

Począwszy od ES2015, radzenie sobie z tym stało się trochę łatwiejsze. String.prototype[@@iterator]zwraca ciągi odpowiadające punktom kodowym **. Na przykład możemy to zrobić:

function capitalizeFirstLetter([ first, ...rest ]) {
  return [ first.toUpperCase(), ...rest ].join('');
}

capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"

W przypadku dłuższych ciągów prawdopodobnie nie jest to strasznie wydajne *** - tak naprawdę nie musimy powtarzać reszty. Moglibyśmy użyć String.prototype.codePointAttej pierwszej (możliwej) litery, ale nadal musielibyśmy ustalić, od czego powinien zacząć się segment. Jednym ze sposobów uniknięcia iteracji reszty byłoby sprawdzenie, czy pierwszy punkt kodowy znajduje się poza BMP; jeśli nie jest, wycinek zaczyna się od 1, a jeśli tak, wycinek zaczyna się od 2.

function capitalizeFirstLetter(str) {
  const firstCP = str.codePointAt(0);
  const index = firstCP > 0xFFFF ? 2 : 1;

  return String.fromCodePoint(firstCP).toUpperCase() + str.slice(index);
}

capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"

Zamiast tego możesz użyć matematyki bitowej > 0xFFFF, ale prawdopodobnie łatwiej jest to zrozumieć i osiągnąć to samo.

Możemy również sprawić, aby działało to w ES5 i niższych, jeśli zajdzie taka potrzeba, posuwając się dalej. W ES5 nie ma żadnych wewnętrznych metod pracy z punktami kodowymi, dlatego musimy ręcznie przetestować, czy pierwsza jednostka kodu jest odpowiednikiem ****:

function capitalizeFirstLetter(str) {
  var firstCodeUnit = str[0];

  if (firstCodeUnit < '\uD800' || firstCodeUnit > '\uDFFF') {
    return str[0].toUpperCase() + str.slice(1);
  }

  return str.slice(0, 2).toUpperCase() + str.slice(2);
}

capitalizeFirstLetter("𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"

Na początku wspomniałem również o kwestiach dotyczących internacjonalizacji. Niektóre z nich są bardzo trudne do wyjaśnienia, ponieważ wymagają wiedzy nie tylko o tym, jakiego języka używa się, ale mogą również wymagać konkretnej znajomości słów w tym języku. Na przykład irlandzki znak „mb” zaczyna się od wielkiej litery jako „mB” na początku słowa. Kolejny przykład, niemiecki eszett, nigdy nie zaczyna słowa (afaik), ale nadal pomaga zilustrować problem. Małe litery eszett („ß”) są wielkimi literami na „SS”, ale „SS” może składać się z małych liter na „ß” lub „ss” - potrzebujesz znajomości języka niemieckiego poza pasmem, aby wiedzieć, który jest prawidłowy!

Najbardziej znanym przykładem tego rodzaju problemów jest prawdopodobnie turecki. W łacinie tureckiej główną formą i jest İ, natomiast mała litera I to ı - są to dwie różne litery. Na szczęście mamy na to sposób:

function capitalizeFirstLetter([ first, ...rest ], locale) {
  return [ first.toLocaleUpperCase(locale), ...rest ].join('');
}

capitalizeFirstLetter("italy", "en") // "Italy"
capitalizeFirstLetter("italya", "tr") // "İtalya"

W przeglądarce najbardziej preferowany znacznik językowy użytkownika jest oznaczony przez navigator.language, lista w kolejności preferencji znajduje się w navigator.languages, a język danego elementu DOM można uzyskać (zwykle) za pomocą Object(element.closest('[lang]')).lang || YOUR_DEFAULT_HEREdokumentów wielojęzycznych.

W agentach, które obsługują klasy znaków właściwości Unicode w RegExp, które zostały wprowadzone w ES2018, możemy dalej posprzątać, bezpośrednio wyrażając, którymi znakami jesteśmy zainteresowani:

function capitalizeFirstLetter(str, locale=navigator.language) {
  return str.replace(/^\p{CWU}/u, char => char.toLocaleUpperCase(locale));
}

Można to nieco ulepszyć, aby obsługiwać wielkie litery w ciągu z dość dobrą dokładnością. Właściwość znakowaCWU lub Changes_When_Uppercased pasuje do wszystkich punktów kodowych, które zmieniają się, gdy są pisane wielkimi literami. Możemy spróbować się z titlecased znaków digraf jak holenderskiego ij na przykład:

capitalizeFirstLetter('ijsselmeer'); // "IJsselmeer"

W momencie pisania (luty 2020) Firefox / Spidermonkey nie wdrożył jeszcze żadnej funkcji RegExp wprowadzonej w ciągu ostatnich dwóch lat *****. Możesz sprawdzić aktualny status tej funkcji w tabeli kompatybilności Kangax . Babel jest w stanie skompilować literały RegExp z odwołaniami do właściwości do równoważnych wzorców bez nich, ale należy pamiętać, że wynikowy kod może być ogromny.


Najprawdopodobniej osoby zadające to pytanie nie będą zajmować się pisaniem wielkich liter ani internacjonalizacją. Ale dobrze jest zdawać sobie sprawę z tych problemów, ponieważ istnieje duża szansa, że ​​w końcu się z nimi spotkasz, nawet jeśli obecnie nie są to obawy. Nie są to przypadki „krawędziowe”, a raczej nie są to przypadki z definicji z definicji - istnieje cały kraj, w którym większość ludzi mówi po turecku, a łączenie jednostek kodowych z punktami kodowymi jest dość powszechnym źródłem błędów (szczególnie z w odniesieniu do emoji). Zarówno łańcuchy, jak i język są dość skomplikowane!


* Jednostki kodowe UTF-16 / UCS2 są również punktami kodowymi Unicode w tym sensie, że np. U + D800 jest technicznie punktem kodowym, ale to nie jest to, co tutaj „znaczy”… tak jakby… chociaż robi się ładnie zamazany. Tym, czym zdecydowanie nie są surogaty, są jednak USV (wartości skalarne Unicode).

** Chociaż jeśli jednostka kodu zastępczego jest „osierocona” - tj. Nie jest częścią logicznej pary - nadal możesz uzyskać tutaj również zastępcze jednostki.

*** może. Nie testowałem tego. Jeśli nie określiłeś, że wielkie litery są znaczącym wąskim gardłem, prawdopodobnie nie przejmowałbym się tym - wybierz wszystko, co Twoim zdaniem jest najbardziej jasne i czytelne.

**** taka funkcja może chcieć przetestować zarówno pierwszą, jak i drugą jednostkę kodu zamiast tylko pierwszej, ponieważ możliwe jest, że pierwsza jednostka jest osieroconym surogatem. Na przykład dane wejściowe „\ uD800x” pisałyby wielką literą X w niezmienionej postaci, czego można oczekiwać lub nie.

***** Oto problem Bugzilli, jeśli chcesz śledzić postępy bardziej bezpośrednio.


2
Ta odpowiedź musi zostać przeniesiona na pierwszy plan.
Rúnar Berg

Dzięki @ RúnarBerg - skoro Twój komentarz mi o tym przypomniał, przeczytałem go jeszcze raz i zdałem sobie sprawę, że pominąłem ostatnią sprawę i rozwiązanie, o którym warto wspomnieć. Próbowałem także lepiej wyjaśnić niektóre terminy.
Średnik

Świetna odpowiedź .....
Ben Aston,

Ta odpowiedź jest doskonała, chciałbym móc ją bardziej głosować.
David Barker,

37

Zawsze lepiej jest najpierw poradzić sobie z tego rodzaju rzeczami za pomocą CSS , ogólnie, jeśli możesz coś rozwiązać za pomocą CSS, najpierw przejdź do tego, a następnie wypróbuj JavaScript, aby rozwiązać problemy, więc w tym przypadku spróbuj użyć :first-letterw CSS i zastosujtext-transform:capitalize;

Spróbuj więc stworzyć klasę do tego, abyś mógł z niej korzystać globalnie, na przykład: .first-letter-uppercasei dodaj coś takiego jak poniżej w swoim CSS:

.first-letter-uppercase:first-letter {
    text-transform:capitalize;
}

Alternatywną opcją jest JavaScript, więc najlepiej będzie coś takiego:

function capitalizeTxt(txt) {
  return txt.charAt(0).toUpperCase() + txt.slice(1); //or if you want lowercase the rest txt.slice(1).toLowerCase();
}

i nazwij to tak:

capitalizeTxt('this is a test'); // return 'This is a test'
capitalizeTxt('the Eiffel Tower'); // return 'The Eiffel Tower'
capitalizeTxt('/index.html');  // return '/index.html'
capitalizeTxt('alireza');  // return 'Alireza'

Jeśli chcesz go używać wielokrotnie, lepiej dołącz go do natywnego ciągu javascript, więc coś w stylu poniżej:

String.prototype.capitalizeTxt = String.prototype.capitalizeTxt || function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
}

i nazwij to jak poniżej:

'this is a test'.capitalizeTxt(); // return 'This is a test'
'the Eiffel Tower'.capitalizeTxt(); // return 'The Eiffel Tower'
'/index.html'.capitalizeTxt();  // return '/index.html'
'alireza'.capitalizeTxt();  // return 'Alireza'

36

Jeśli chcesz sformatować tekst wielkimi literami, możesz zmodyfikować inne przykłady jako takie:

function capitalize (text) {
    return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
}

Zapewni to zmianę następującego tekstu:

TEST => Test
This Is A TeST => This is a test

Prawdopodobnie warto zauważyć, że to również przekształci takie rzeczy jak akronimy na małe litery, więc może nie jest to najlepszy pomysł w większości przypadków
monokrom

Ponadto, czy GAMITG naprawdę dokonał edycji tylko po to, aby usunąć fragment spacji z niekodowej części postu? O_O
monokrome

btw, to złamie górne akronimy, więc uważajcie wszyscy <3
monokrom

34
function capitalize(s) {
    // returns the first letter capitalized + the string from index 1 and out aka. the rest of the string
    return s[0].toUpperCase() + s.substr(1);
}


// examples
capitalize('this is a test');
=> 'This is a test'

capitalize('the Eiffel Tower');
=> 'The Eiffel Tower'

capitalize('/index.html');
=> '/index.html'

Gotowe @Ram. Zawiera również przykłady.
Fredrik A.,

Jak to jest lepsze niż odpowiedź z 2009 roku ?
Dan Dascalescu

1
To nie jest @DanDascalescu. Przypuszczam, że można argumentować, że substr/ substringjest nieco bardziej semantyczny w przeciwieństwie do slice, ale to tylko kwestia preferencji. Dołączyłem jednak przykłady z ciągami podanymi w pytaniu, co jest miłym akcentem nieobecnym w przykładzie z 09. Szczerze mówiąc, myślę, że sprowadza się to do 15-letniego mnie, który chce karmy na StackOverflow;)
Fredrik A.,

34

Oto funkcja o nazwie ucfirst () (skrót od „wielka pierwsza litera”):

function ucfirst(str) {
    var firstLetter = str.substr(0, 1);
    return firstLetter.toUpperCase() + str.substr(1);
}

Możesz napisać wielką literą, wywołując ucfirst („jakiś ciąg”) - na przykład

ucfirst("this is a test") --> "This is a test"

Działa poprzez podział struny na dwie części. W pierwszym wierszu wyciąga firstLetter, a następnie w drugim wierszu kapitalizuje firstLetter , wywołując firstLetter.toUpperCase () i łączy go z resztą ciągu, który można znaleźć, wywołując str.substr (1) .

Możesz pomyśleć, że to nie powiedzie się dla pustego łańcucha, a nawet w języku takim jak C musiałbyś się tym zająć. Jednak w JavaScript, gdy weźmiesz podciąg pustego łańcucha, po prostu odzyskasz pusty łańcuch.


4
Użyj String.substring () lub String.slice () ... Nie używaj substr () - jest przestarzałe.
James

7
@ 999: gdzie to substr()jest przestarzałe? To nie jest nawet teraz, trzy lata później, a co dopiero w 2009 roku, kiedy skomentowałeś ten komentarz.
Dan Dascalescu,

substr()może nie być oznaczony jako przestarzały przez żadną popularną implementację ECMAScript (wątpię, że wkrótce nie zniknie), ale nie jest to część specyfikacji ECMAScript. Trzecie wydanie specyfikacji wspomina o tym w nienormatywnym załączniku, aby „sugerować jednolitą semantykę dla takich właściwości bez włączania właściwości lub ich semantyki do tego standardu”.
Peter Rust

2
Mając na 3 sposoby, które robią to samo ( substring, substri slice) jest zbyt wiele, IMO. Zawsze używam, sliceponieważ obsługuje ujemne indeksy, nie ma mylących zachowań polegających na zamianie argów, a jego interfejs API jest podobny do sliceinnych języków.
Peter Rust

29
String.prototype.capitalize = function(){
    return this.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase();
    } );
};

Stosowanie:

capitalizedString = someString.capitalize();

To jest ciąg tekstowy => To jest ciąg tekstowy


20
Wyrażenia regularne są w tym przypadku przesadą.
Anthony Sottile

+1, tego naprawdę szukałem. Jest jednak drobny błąd, powinien to być return.this.toLocaleLowerCase().replace(...
tomdemuyt

+1, znalazłem tę stronę w poszukiwaniu javascriptowej wersji phps ucfirst, co, jak podejrzewam, to sposób, w jaki większość ludzi ją znajduje.
Benubird

@DanDascalescu Uznałem to za użyteczne, więc +1 do utylitaryzmu i -1 do zatrzymania analu. Podał przykład, więc jego funkcja jest jasna.
Travis Webb,

String.prototype.capitalize = function(){ return this.replace( /(^|\s)[a-z]/g , function(m){ return m.toUpperCase(); }); }; Trochę zmieniam kod, potrzebujesz tylko pierwszego dopasowania.
IGRACH

28
var str = "test string";
str = str.substring(0,1).toUpperCase() + str.substring(1);

21

Sprawdź to rozwiązanie:

var stringVal = 'master';
stringVal.replace(/^./, stringVal[0].toUpperCase()); // returns Master 

3
To powinna być zaakceptowana odpowiedź. Główne rozwiązanie nie powinno korzystać z frameworku takiego jak podkreślenie.
Adam McArthur,

3
Zaoszczędź trochę klawiszy;)stringVal.replace(/^./, stringVal[0].toUpperCase());
Alfredo Delgado

1
Regex nie powinien być stosowany tam, gdzie nie jest to konieczne. Jest bardzo nieefektywny i nie czyni też kodu bardziej zwięzłym. Co więcej, stringVal[0]byłoby undefinedpuste stringVal, i jako taka próba dostępu do nieruchomości .toUpperCase()spowodowałaby błąd.
Przemek

20
yourString.replace(/^[a-z]/, function(m){ return m.toUpperCase() });

(Możesz obudować go funkcją lub nawet dodać do prototypu String, jeśli często go używasz.)


5
Mimo, że ma dość sporo głosów, jest to zdecydowanie najwolniejsze rozwiązanie opublikowane tutaj. Przygotowałem mały test szybkościowy
Robin van Baalen

@RobinvanBaalen Twój link jest teraz uszkodzony. Masz zaktualizowany?
Brad

1
Regexp jest do tego przesadny, wolę prościej: str.charAt (0) .toUpperCase () + str.slice (1)
Simon

@Brad niestety nie
Robin van Baalen

Często, jeśli chcesz rozwiązać swój problem z wyrażeniem regularnym, możesz spotkać się z dwoma problemami.
Przemek

19

ucfirstFunkcja działa, jeśli robisz to w ten sposób.

function ucfirst(str) {
    var firstLetter = str.slice(0,1);
    return firstLetter.toUpperCase() + str.substring(1);
}

Dzięki JP za deklarację.


2
ładna nazwa funkcji! Jego nazwa jest identyczna z odpowiednikiem PHP. W rzeczywistości istnieje cała biblioteka funkcji PHP napisanych w JS; nazywa się PHP.js i można go znaleźć na stronie http://phpjs.org
Hussam

11
Jedna linijka:string[0].toUpperCase() + string.substring(1)
dr.dimitru,

@TarranJones tutaj jest kuloodporny jeden wkładka:(string[0] || '').toUpperCase() + string.substring(1)
dr.dimitru

@ dr.dimitru: Zamiast idiomatycznego (string[0] || '')możesz po prostu string.charAt(0).
Przemek


17
yourString.replace(/\w/, c => c.toUpperCase())

Ta funkcja strzałki była dla mnie najłatwiejsza. Zamień dopasowuje pierwszą literę ( \w) łańcucha i konwertuje ją na wielkie litery. Nie potrzeba nic bardziej wymyślnego.


1
To powinna być zaakceptowana odpowiedź, zamiast tego jest prawie ostatnia, ponieważ SO wciąż przyznaje nieaktualne pytania. Btw, lepiej jest użyć /./z dwóch powodów: /\w/pominie wszystkie poprzednie znaki
nieliterowe
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.